JavaRush /وبلاگ جاوا /Random-FA /بهار برای تنبل هاست مبانی، مفاهیم اولیه و مثال هایی با کد...
Стас Пасинков
مرحله
Киев

بهار برای تنبل هاست مبانی، مفاهیم اولیه و مثال هایی با کد. قسمت 2

در گروه منتشر شد
در آخرین مقاله به طور خلاصه توضیح دادم که بهار چیست، سطل زباله چیست و زمینه چیست. اکنون زمان آن رسیده است که سعی کنید همه چیز چگونه کار می کند. بهار برای تنبل هاست  مبانی، مفاهیم اولیه و مثال هایی با کد.  قسمت 2 - 1من خودم این کار را در Intellij Idea Enterprise Edition انجام خواهم داد. اما همه نمونه‌های من باید در نسخه رایگان جامعه ایده Intellij نیز کار کنند. فقط اگر در اسکرین شات ها می بینید که من نوعی پنجره دارم که شما آن را ندارید، نگران نباشید، برای این پروژه مهم نیست :) ابتدا، اجازه دهید یک پروژه خالی Maven ایجاد کنیم. من نحوه انجام این کار را در مقاله نشان دادم (تا کلمات " وقت آن است که پروژه maven خود را به یک پروژه وب تبدیل کنیم " را بخوانید. پس از آن قبلاً نحوه ایجاد یک پروژه وب را نشان می دهد و ما اکنون به این نیاز نداریم) بیایید آن را در پوشه src/main / java is some package ایجاد کنیم (در مورد من آن را " ru.javarush.info.fatfaggy.animals" نامیدم، می توانید نام آن را هر چه می خواهید بگذارید، فقط فراموش نکنید که آن را با نام خود در مکان های مناسب جایگزین کنید). و بیایید یک کلاس ایجاد کنیم Mainکه در آن یک متد بسازیم
public static void main(String[] args) {
    ...
}
سپس فایل pom.xml را باز کرده و بخشی را در آنجا اضافه کنید dependencies. اکنون به مخزن Maven می رویم و به دنبال زمینه بهار آخرین نسخه پایدار در آنجا می گردیم و آنچه را که به دست آورده ایم را در داخل بخش قرار می دهیم dependencies. من این فرآیند را در این مقاله با کمی جزئیات بیشتر توضیح دادم (به بخش " اتصال وابستگی ها در Maven " مراجعه کنید). سپس خود Maven وابستگی های لازم را پیدا و دانلود می کند و در پایان باید چیزی شبیه به این دریافت کنید:
بهار برای تنبل هاست  مبانی، مفاهیم اولیه و مثال هایی با کد.  قسمت 2 - 2
در پنجره سمت چپ می توانید ساختار پروژه را با بسته و کلاس مشاهده کنید Main. پنجره وسط نشان می دهد که pom.xml من چگونه است. من همچنین یک بخش خصوصیات را در آنجا اضافه کردم که در آن به Maven نشان دادم که از کدام نسخه جاوا در کد منبع استفاده می کنم و در کدام نسخه کامپایل کنم. این فقط به این دلیل است که هنگام راه‌اندازی هشداری مبنی بر استفاده از یک نسخه قدیمی جاوا دریافت نکنم. شما می توانید آن را انجام دهید، نمی توانید) در پنجره سمت راست - می توانید ببینید که حتی اگر ما فقط زمینه بهار را به هم وصل کردیم - به طور خودکار هسته، beans، aop و بیان را اضافه کرد. امکان اتصال هر ماژول به طور جداگانه وجود داشت و برای هر کدام یک وابستگی در حافظه با یک نشانه صریح از نسخه ثبت می شد، اما در حال حاضر ما از گزینه ای که اکنون هست راضی هستیم. حالا بیایید یک بسته entities(موجودات) ایجاد کنیم و 3 کلاس در آن ایجاد کنیم: Cat, Dog, Parrot. اجازه دهید هر حیوانی یک نام داشته باشد ( private String name، می‌توانید برخی از مقادیر را در آنجا کدگذاری کنید)، و دریافت‌کننده‌ها/تنظیم‌کننده‌ها عمومی هستند. حالا به کلاس بروید Mainو main()چیزی شبیه به این را در متد بنویسید:
public static void main(String[] args) {
	// create an empty spring context that will search for its beans by annotations in the specified package
	ApplicationContext context =
		new AnnotationConfigApplicationContext("ru.javarush.info.fatfaggy.animals.entities");

	Cat cat = context.getBean(Cat.class);
	Dog dog = (Dog) context.getBean("dog");
	Parrot parrot = context.getBean("parrot-kesha", Parrot.class);

	System.out.println(cat.getName());
	System.out.println(dog.getName());
	System.out.println(parrot.getName());
}
ابتدا یک Object Context ایجاد می کنیم و در سازنده نام بسته ای را که باید برای وجود beans اسکن شود به آن می دهیم. یعنی Spring از این بسته عبور می کند و سعی می کند کلاس هایی را پیدا کند که با حاشیه نویسی خاصی مشخص شده اند که به Spring بفهمد که این یک لوبیا است. پس از آن، اشیاء این کلاس ها را ایجاد می کند و آنها را در متن خود قرار می دهد. پس از آن ما یک گربه از این زمینه می گیریم. هنگام پرداختن به آبجکت متنی، از آن می‌خواهیم که یک bean (ابجکت) به ما بدهد و نشان دهد که به چه کلاسی از شی نیاز داریم (در اینجا، اتفاقاً می‌توانید نه تنها کلاس‌ها، بلکه رابط‌ها را نیز مشخص کنید). پس از آن Spring یک شی از این کلاس را به ما برمی گرداند که آن را در یک متغیر ذخیره می کنیم. در مرحله بعد، از بهار می خواهیم که لوبیایی به نام "سگ" برای ما بیاورد. هنگامی که Spring یک شی کلاس ایجاد می کند، Dogیک نام استاندارد به آن می دهد (اگر نام bean در حال ایجاد به صراحت مشخص نشده باشد)، که نام کلاس شی است، فقط با یک حرف کوچک. بنابراین، از آنجایی که کلاس ما نام دارد Dog، نام چنین لوبیا "سگ" خواهد بود. اگر یک شی در آنجا داشتیم BufferedReader، اسپرینگ نام پیش‌فرض "bufferedReader" را به آن می‌داد. و از آنجایی که در این مورد (در جاوا) اطمینان دقیقی از اینکه چنین شیئی چه کلاسی خواهد بود وجود ندارد، به سادگی یک مورد معین برگردانده می شود Object، که سپس به صورت دستی به نوع مورد نیاز خود ارسال می کنیم Dog. گزینه ای با نشانه صریح کلاس راحت تر است. خوب، در مورد سوم، یک لوبیا به کلاس و نام می گیریم. ممکن است به سادگی شرایطی وجود داشته باشد که در زمینه چندین دانه از یک کلاس وجود داشته باشد، و برای اینکه مشخص کنیم به کدام دانه خاص نیاز داریم، نام آن را نشان می دهیم. از آنجایی که ما کلاس را نیز در اینجا به وضوح نشان دادیم، دیگر نیازی به بازیگری نداریم. مهم!اگر معلوم شود که اسپرینگ با توجه به الزاماتی که برایش مشخص کرده ایم، چندین لوبیا پیدا می کند، نمی تواند تعیین کند که کدام لوبیا را به ما بدهد و استثنا می اندازد. بنابراین سعی کنید تا حد امکان به او نشان دهید که به کدام سطل زباله نیاز دارید تا چنین شرایطی پیش نیاید. اگر بهار با توجه به شرایط شما یک لوبیا در بافت خود پیدا نکند استثنا هم می اندازد. خوب، پس ما به سادگی نام حیوانات خود را روی صفحه نمایش می دهیم تا مطمئن شویم که اینها واقعاً اشیایی هستند که ما نیاز داریم. اما اگر اکنون برنامه را اجرا کنیم، می بینیم که بهار سوگند یاد می کند که نمی تواند حیوانات مورد نیاز ما را در متن خود پیدا کند. این اتفاق به این دلیل افتاد که او این لوبیاها را خلق نکرد. همانطور که قبلاً گفتم، وقتی Spring کلاس ها را اسکن می کند، به دنبال حاشیه نویسی Spring "خود" در آنجا می گردد. و اگر آن را پیدا نکرد، پس چنین طبقاتی را مانند آنهایی که باید دانه هایشان را ایجاد کند، درک نمی کند. برای رفع این مشکل، به سادگی یک حاشیه نویسی @Componentدر جلوی کلاس در کلاس های حیوانات خود اضافه کنید.
@Component
public class Cat {
	private String name = "Barsik";
	...
}
اما این همه ماجرا نیست. اگر بخواهیم به صراحت به Spring نشان دهیم که bean برای این کلاس باید یک نام خاص داشته باشد، این نام را می توان در پرانتز بعد از حاشیه نشان داد. به عنوان مثال، برای اینکه اسپرینگ نام مورد نیاز خود را به parrot-keshaلوبیا طوطی بدهد که mainبعداً این طوطی را از آن دریافت خواهیم کرد، باید این کار را انجام دهیم:
@Component("parrot-kesha")
public class Parrot {
	private String name = "Kesha";
	...
}
این تمام نکته پیکربندی خودکار است . شما کلاس های خود را می نویسید، آنها را با حاشیه نویسی های لازم علامت گذاری می کنید و بسته ای را با کلاس های خود به Spring نشان می دهید، که از طریق آن می رود، به دنبال حاشیه نویسی می گردد و اشیایی از چنین کلاس هایی ایجاد می کند. به هر حال، Spring نه تنها حاشیه نویسی ها @Component، بلکه سایر حاشیه نویسی هایی که از این مورد به ارث رسیده اند را نیز جستجو می کند. به عنوان مثال ، @Controller، @RestController، @Service، @Repositoryو موارد دیگر که در مقالات بعدی با آنها آشنا خواهیم شد. حالا بیایید سعی کنیم همین کار را انجام دهیم، اما با استفاده از پیکربندی جاوا . ابتدا، بیایید حاشیه نویسی را @Componentاز کلاس های خود حذف کنیم. برای پیچیده‌تر کردن کار، بیایید تصور کنیم که این‌ها کلاس‌های خودنویس خودمان نیستند، که می‌توانیم به راحتی آن‌ها را تغییر دهیم، چیزی اضافه کنیم، از جمله حاشیه‌نویسی. گویی این کلاس ها در یک کتابخانه جمع شده اند. در این صورت به هیچ وجه نمی توانیم این کلاس ها را طوری ویرایش کنیم که تا بهار پذیرفته شوند. اما ما به آبجکت هایی از این کلاس ها نیاز داریم! در اینجا برای ایجاد چنین اشیایی به پیکربندی جاوا نیاز داریم. برای شروع، اجازه دهید یک بسته، به عنوان مثال configs، و در آن - به عنوان مثال یک کلاس جاوای معمولی ایجاد کنیم، MyConfigو آن را با یک حاشیه نویسی علامت گذاری کنیم.@Configuration
@Configuration
public class MyConfig {
}
اکنون باید main()نحوه ایجاد زمینه در متد را کمی تغییر دهیم. ما می توانیم مستقیماً کلاس خود را با پیکربندی در آنجا مشخص کنیم:
ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class);
اگر چندین کلاس مختلف داشته باشیم که در آنها bean ایجاد می کنیم و می خواهیم چند تا از آنها را همزمان به هم وصل کنیم، به سادگی آنها را با کاما از هم جدا می کنیم:
ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class, MyAnotherConfig.class);
خوب، اگر تعداد زیادی از آنها داریم و می خواهیم همه آنها را به یکباره وصل کنیم، به سادگی نام بسته ای را که در آن داریم نشان می دهیم:
ApplicationContext context =
	new AnnotationConfigApplicationContext("ru.javarush.info.fatfaggy.animals.configs");
در این صورت، Spring از این بسته عبور می کند و تمام کلاس هایی که با حاشیه نویسی مشخص شده اند را پیدا می کند @Configuration. خوب، در صورتی که ما یک برنامه واقعا بزرگ داریم که در آن تنظیمات به بسته های مختلف تقسیم می شوند، ما به سادگی نام بسته ها را با پیکربندی هایی که با کاما از هم جدا شده اند نشان می دهیم:
ApplicationContext context =
	new AnnotationConfigApplicationContext("ru.javarush.info.fatfaggy.animals.database.configs",
		"ru.javarush.info.fatfaggy.animals.root.configs",
		"ru.javarush.info.fatfaggy.animals.web.configs");
خوب، یا نام بسته ای که برای همه آنها مشترک است:
ApplicationContext context =
	new AnnotationConfigApplicationContext("ru.javarush.info.fatfaggy.animals");
شما می توانید آن را هر طور که می خواهید انجام دهید، اما به نظر من اولین گزینه، که در آن شما به سادگی یک کلاس را با تنظیمات مشخص می کنید، بهترین گزینه برای برنامه ما خواهد بود. هنگام ایجاد یک زمینه، Spring برای کلاس هایی که با حاشیه نویسی مشخص شده اند جستجو می کند @Configurationو اشیاء این کلاس ها را در خود ایجاد می کند. پس از آن سعی می‌کند متدهایی را در این کلاس‌ها فراخوانی کند که با حاشیه‌نویسی مشخص شده‌اند @Bean، به این معنی که چنین روش‌هایی beans (اشیاء) را که قبلاً در متن خود قرار داده است، برمی‌گردانند. خوب، حالا بیایید دانه های گربه، سگ و طوطی را در کلاس خود با پیکربندی جاوا ایجاد کنیم. این به سادگی انجام می شود:
@Bean
public Cat getCat() {
	return new Cat();
}
معلوم شد که ما خودمان گربه مان را به صورت دستی خلق کردیم و به اسپرینگ دادیم و او قبلاً این شی ما را در بافت خود قرار داده بود. از آنجایی که ما به صراحت نام bean خود را مشخص نکردیم، Spring همان نام bean را با نام متد انتخاب می کند. در مورد ما، لوبیا گربه نام " getCat" خواهد داشت. اما از آنجایی که در main-e ما هنوز گربه را نه با نام، بلکه بر اساس کلاس دریافت می کنیم، پس در این مورد نام این سطل برای ما مهم نیست. یک لوبیا با سگ هم به همین ترتیب درست کنید اما در نظر داشته باشید که اسپرینگ اسم این گونه لوبیا را به اسم روش می گذارد. برای نام‌گذاری صریح لوبیا با طوطی، کافی است نام آن را در پرانتز بعد از حاشیه‌نویسی مشخص کنید @Bean:
@Bean("parrot-kesha")
public Object weNeedMoreParrots() {
	return new Parrot();
}
همانطور که می بینید، در اینجا نوع مقدار بازگشتی را نشان دادم Objectو روش را هر چیزی نامیدم. این به هیچ وجه روی نام لوبیا تأثیر نمی گذارد زیرا ما به صراحت آن را در اینجا تنظیم می کنیم. اما بهتر است نوع مقدار بازگشتی و نام روش را نه به صورت آبی، بلکه کمابیش واضح نشان دهید. حتی برای خودتان، وقتی این پروژه را در یک سال افتتاح می کنید. :) حالا بیایید شرایطی را در نظر بگیریم که برای ایجاد یک لوبیا باید از یک لوبیا دیگر استفاده کنیم . به عنوان مثال، ما می خواهیم نام گربه در لوبیا گربه شامل نام طوطی و رشته "-killer" باشد. مشکلی نیست!
@Bean
public Cat getCat(Parrot parrot) {
	Cat cat = new Cat();
	cat.setName(parrot.getName() + "-killer");
	return cat;
}
در اینجا اسپرینگ می بیند که قبل از ایجاد این لوبیا، باید لوبیای طوطی از قبل ایجاد شده را به اینجا منتقل کند. بنابراین او یک زنجیره فراخوانی به متدهای ما خواهد ساخت تا ابتدا متد ایجاد طوطی فراخوانی شود و سپس این طوطی را به متد ایجاد گربه منتقل کند. این همان جایی است که چیزی به نام تزریق وابستگی کار کرد : اسپرینگ خود لوبیا طوطی مورد نیاز را به روش ما منتقل کرد. اگر ایده از متغیری شکایت دارد parrot، فراموش نکنید که نوع بازگشت را در روش ایجاد طوطی از Objectبه تغییر دهید Parrot. علاوه بر این، پیکربندی جاوا به شما این امکان را می دهد که کاملاً هر کد جاوا را در روش های ایجاد دانه ها اجرا کنید. شما واقعاً می توانید هر کاری انجام دهید: اشیاء کمکی دیگری ایجاد کنید، هر روش دیگری را فراخوانی کنید، حتی آنهایی که با حاشیه نویسی بهار مشخص نشده اند، حلقه ها، شرایط - هر چه به ذهنتان می رسد! همه اینها را نمی توان با استفاده از پیکربندی خودکار به دست آورد، بسیار کمتر با استفاده از تنظیمات xml. حالا بیایید به یک مشکل سرگرم کننده تر نگاه کنیم. با چند شکلی و رابط :) بیایید یک رابط ایجاد کنیم و WeekDay7 کلاس ایجاد کنیم که این رابط را پیاده سازی کند: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday. Sundayبیایید یک متد در رابط ایجاد کنیم String getWeekDayName()که نام روز هفته کلاس مربوطه را برگرداند. یعنی کلاس " " و غیره Mondayرا برمی‌گرداند . mondayبیایید بگوییم وظیفه هنگام راه اندازی برنامه ما این است که یک لوبیا را در زمینه ای قرار دهیم که مطابق با روز جاری هفته باشد. نه همه دانه‌ها از همه کلاس‌ها که WeekDayاینترفیس را پیاده‌سازی می‌کنند، بلکه فقط آن چیزی که ما نیاز داریم. می توان چیزی شبیه به این انجام داد:
@Bean
public WeekDay getDay() {
	DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
	switch (dayOfWeek) {
		case MONDAY: return new Monday();
		case TUESDAY: return new Tuesday();
		case WEDNESDAY: return new Wednesday();
		case THURSDAY: return new Thursday();
		case FRIDAY: return new Friday();
		case SATURDAY: return new Saturday();
		default: return new Sunday();
	}
}
در اینجا نوع مقدار بازگشتی اینترفیس ما است و متد اشیاء واقعی کلاس های پیاده سازی رابط را بسته به روز جاری هفته برمی گرداند. حالا در متد main()می توانیم این کار را انجام دهیم:
WeekDay weekDay = context.getBean(WeekDay.class);
System.out.println("It's " + weekDay.getWeekDayName() + " today!");
به من گفت امروز یکشنبه است :) مطمئنم اگر فردا برنامه را اجرا کنم یک شی کاملاً متفاوت در متن ظاهر می شود. لطفاً توجه داشته باشید که در اینجا ما لوبیا را به سادگی با رابط کاربری دریافت می کنیم: context.getBean(WeekDay.class). Spring به متن خود نگاه می کند تا ببیند کدام یک از bean هایش چنین رابطی را پیاده سازی می کند و آن را برمی گرداند. خوب، پس معلوم می شود که WeekDayیک شی از نوع در متغیری از نوع وجود دارد Sunday، و چندشکلی، که قبلاً برای همه ما آشناست، هنگام کار با این متغیر شروع می شود. :) و چند کلمه در مورد رویکرد ترکیبی ، جایی که برخی از bean ها توسط خود Spring ایجاد می شوند، با استفاده از اسکن بسته ها برای حضور کلاس ها با حاشیه نویسی @Component، و برخی از bean ها با استفاده از پیکربندی جاوا ایجاد می شوند. برای انجام این کار، اجازه دهید به نسخه اصلی برگردیم، زمانی که کلاس‌ها Catبا یک حاشیه‌نویسی مشخص Dogشدند . فرض کنید می‌خواهیم با استفاده از اسکن خودکار بسته‌ها تا بهار، سطل‌هایی برای حیوانات خود ایجاد کنیم، اما یک سطل با روز هفته درست کنیم. تنها کاری که باید انجام دهید این است که در سطح کلاس اضافه کنید ، که در هنگام ایجاد زمینه در حاشیه نویسی -ام مشخص می کنیم ، و بسته ای را که باید اسکن شود و دانه های کلاس های لازم به طور خودکار ایجاد می شود را در پرانتز نشان می دهیم: Parrot@ComponententitiesMyConfigmain@ComponentScan
@Configuration
@ComponentScan("ru.javarush.info.fatfaggy.animals.entities")
public class MyConfig {
	@Bean
	public WeekDay getDay() {
		DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
		switch (dayOfWeek) {
			case MONDAY: return new Monday();
			case TUESDAY: return new Tuesday();
			case WEDNESDAY: return new Wednesday();
			case THURSDAY: return new Thursday();
			case FRIDAY: return new Friday();
			case SATURDAY: return new Saturday();
			default: return new Sunday();
		}
	}
}
به نظر می رسد که هنگام ایجاد یک زمینه، Spring می بیند که باید کلاس را پردازش کند MyConfig. او به داخل آن می رود و می بیند که باید بسته " ru.javarush.info.fatfaggy.animals.entities" را اسکن کند و beans از آن کلاس ها را ایجاد کند، پس از آن متد را getDay()از کلاس اجرا می کند MyConfigو نوع bean را WeekDayبه متن خود اضافه می کند. در روش، main()ما اکنون به تمام لوبیاهایی که نیاز داریم دسترسی داریم: هم اشیاء حیوانی و هم لوبیا با روز هفته. چگونه مطمئن شویم که Spring برخی از تنظیمات xml را نیز انتخاب می کند - در صورت لزوم خودتان آن را در اینترنت جستجو کنید :) خلاصه:
  • سعی کنید از پیکربندی خودکار استفاده کنید.
  • در طول پیکربندی خودکار، نام بسته حاوی کلاس هایی را که باید beans ایجاد شود، نشان می دهیم.
  • چنین کلاس هایی با یک حاشیه مشخص شده اند@Component;
  • بهار از همه این طبقات می گذرد و اشیاء آنها را ایجاد می کند و آنها را در بافت قرار می دهد.
  • اگر پیکربندی خودکار به دلایلی مناسب ما نیست، از پیکربندی جاوا استفاده می کنیم.
  • در این حالت، ما یک کلاس جاوای معمولی ایجاد می کنیم که متدهای آن اشیاء مورد نیاز ما را برمی گرداند و @Configurationدر صورتی که کل بسته را اسکن کنیم به جای تعیین یک کلاس خاص با پیکربندی هنگام ایجاد زمینه، چنین کلاسی را با یک حاشیه مشخص می کنیم.
  • روش‌های این کلاس که beanهای برگشتی با حاشیه‌نویسی مشخص می‌شوند @Bean.
  • اگر بخواهیم هنگام استفاده از پیکربندی جاوا، اسکن خودکار را فعال کنیم، از حاشیه نویسی استفاده می کنیم @ComponentScan.
اگر هیچ چیز واضح نیست، پس سعی کنید این مقاله را چند روز دیگر بخوانید. خوب، یا اگر در سطوح اولیه جاوراش هستید، شاید برای یادگیری بهار کمی زود باشد. همیشه می توانید کمی دیرتر به این مقاله بازگردید، زمانی که در برنامه نویسی در جاوا احساس اطمینان بیشتری کردید. اگر همه چیز مشخص است، می توانید سعی کنید برخی از پروژه های حیوان خانگی خود را به Spring منتقل کنید :) اگر چیزی واضح است، اما چیزی زیاد نیست، لطفا نظر دهید :) همچنین پیشنهادات و نظراتی وجود دارد اگر جایی قدم گذاشتم یا چیز احمقانه ای نوشتم ) در مقاله بعدی به بررسی عمیق Spring-web-mvc خواهیم پرداخت و یک برنامه وب ساده با استفاده از فنر می سازیم.
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION