JavaRush /مدونة جافا /Random-AR /الربيع للكسالى. الأساسيات والمفاهيم الأساسية والأمثلة مع ...
Стас Пасинков
مستوى
Киев

الربيع للكسالى. الأساسيات والمفاهيم الأساسية والأمثلة مع التعليمات البرمجية. الجزء 2

نشرت في المجموعة
في المقالة الأخيرة ، شرحت باختصار ما هو الربيع، وما هي الصناديق والسياق. الآن حان الوقت لتجربة كيفية عمل كل شيء. الربيع للكسالى.  الأساسيات والمفاهيم الأساسية والأمثلة مع التعليمات البرمجية.  الجزء 2 - 1سأفعل ذلك بنفسي في Intellij Idea Enterprise Edition. ولكن يجب أن تعمل جميع الأمثلة الخاصة بي أيضًا في إصدار Intellij Idea Community Edition المجاني. فقط إذا رأيت في لقطات الشاشة أن لدي نافذة ليست لديك، فلا تقلق، فهذا ليس ضروريًا لهذا المشروع :) أولاً، لنقم بإنشاء مشروع Maven فارغًا. لقد أوضحت كيفية القيام بذلك في المقالة (اقرأ حتى الكلمات " حان الوقت لتحويل مشروعنا المخضرم إلى مشروع ويب. "، بعد ذلك يظهر بالفعل كيفية إنشاء مشروع ويب، ولا نحتاج إلى هذا الآن) لنقم بإنشائه في المجلد src/main /java عبارة عن حزمة ما (في حالتي أسميتها " 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 إصدار Java الذي كنت أستخدمه في الكود المصدري والإصدار الذي سيتم التحويل إليه. هذا فقط حتى لا أحصل على فكرة التحذير عند بدء التشغيل من استخدام إصدار قديم من Java. يمكنك فعل ذلك، لا يمكنك) في النافذة اليمنى - يمكنك أن ترى أنه على الرغم من أننا قمنا بتوصيل سياق الربيع فقط - فقد أضاف تلقائيًا النواة والفاصوليا و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());
}
أولاً، نقوم بإنشاء كائن سياق، وفي المُنشئ نعطيه اسم الحزمة التي يجب فحصها بحثًا عن وجود الحبوب. أي أن Spring سوف يراجع هذه الحزمة ويحاول العثور على فئات تم تمييزها بتعليقات توضيحية خاصة تتيح لـ Spring معرفة أن هذه حبة فول. وبعد ذلك يقوم بإنشاء كائنات من هذه الفئات ويضعها في سياقه. وبعد ذلك نحصل على قطة من هذا السياق. عند معالجة كائن السياق، نطلب منه أن يعطينا حبة (كائن)، ويشير إلى فئة الكائن التي نحتاجها (هنا، بالمناسبة، لا يمكنك تحديد الفئات فحسب، بل يمكنك أيضًا تحديد الواجهات). وبعد ذلك يقوم Spring بإرجاع كائن من هذه الفئة إلينا، والذي نقوم بحفظه في متغير. بعد ذلك، نطلب من الربيع أن يحضر لنا حبة فول تسمى "الكلب". عندما ينشئ Spring كائن فئة، Dogفإنه سيعطيه اسمًا قياسيًا (إذا لم يتم تحديد اسم الحبة التي تم إنشاؤها بشكل صريح)، وهو اسم فئة الكائن، فقط بحرف صغير. لذلك، نظرًا لأن فصلنا يسمى " Dog،" فإن اسم هذه الحبة سيكون "كلب". إذا كان لدينا كائن هناك BufferedReader، فسيعطيه Spring الاسم الافتراضي "bufferedReader". وبما أنه في هذه الحالة (في Java) لا يوجد يقين دقيق بشأن الفئة التي سيكون عليها هذا الكائن، فسيتم ببساطة إرجاع كائن معين Object، والذي نقوم بعد ذلك بتحويله يدويًا إلى النوع الذي نحتاجه Dog. يعد الخيار الذي يحتوي على إشارة صريحة للفئة أكثر ملاءمة. حسنًا، في الحالة الثالثة، نحصل على حبة حسب الفئة والاسم. قد يكون هناك ببساطة موقف حيث سيكون هناك عدة حبوب من فئة واحدة في السياق، ومن أجل الإشارة إلى الفول الذي نحتاجه، نشير إلى اسمه. نظرًا لأننا أشرنا أيضًا إلى الفصل بوضوح هنا، فلم يعد يتعين علينا الإدلاء به. مهم!إذا اتضح أن Spring عثر على العديد من الحبوب وفقًا للمتطلبات التي حددناها له، فلن يتمكن من تحديد الحبوب التي سيقدمها لنا وسيطرح استثناءً. لذلك، حاول أن تشير إليه بأكبر قدر ممكن من الدقة، ما هو الصندوق الذي تحتاجه، حتى لا تنشأ مثل هذه المواقف. إذا لم يعثر Spring على حبة واحدة في سياقها وفقًا لشروطك، فسيقوم أيضًا بطرح استثناء. حسنًا، بعد ذلك نقوم ببساطة بعرض أسماء حيواناتنا على الشاشة للتأكد من أنها في الواقع هي الكائنات التي نحتاجها بالضبط. لكن إذا قمنا بتشغيل البرنامج الآن، فسنرى أن سبرينج يقسم أنه لا يستطيع العثور على الحيوانات التي نحتاجها في سياقه. حدث هذا لأنه لم يخلق هذه الفاصوليا. كما قلت سابقًا، عندما يقوم Spring بفحص الفصول الدراسية، فإنه يبحث عن التعليقات التوضيحية الربيعية الخاصة به هناك. وإذا لم يجدها، فإنه لا يرى مثل هذه الطبقات مثل تلك التي يحتاج إلى إنشاء حبوبها. لإصلاح هذه المشكلة، ما عليك سوى إضافة تعليق توضيحي @Componentأمام الفصل في فئات الحيوانات لدينا.
@Component
public class Cat {
	private String name = "Barsik";
	...
}
ولكن هذا ليس كل شيء. إذا أردنا أن نشير صراحة إلى Spring أن حبة هذه الفئة يجب أن يكون لها اسم محدد، فيمكن الإشارة إلى هذا الاسم بين قوسين بعد التعليق التوضيحي. على سبيل المثال، لكي يعطي Spring الاسم الذي نحتاجه لفاصوليا parrot-keshaالببغاء، والتي سنتلقى منها mainهذا الببغاء لاحقًا، نحتاج إلى القيام بشيء مثل هذا:
@Component("parrot-kesha")
public class Parrot {
	private String name = "Kesha";
	...
}
هذا هو بيت القصيد من التكوين التلقائي . تكتب فصولك، وتضع علامة عليها بالتعليقات التوضيحية اللازمة، وتشير إلى Spring حزمة تحتوي على فصولك، والتي من خلالها تذهب، وتبحث عن التعليقات التوضيحية، وتنشئ كائنات من هذه الفئات. بالمناسبة، لن يبحث Spring عن التعليقات التوضيحية فحسب @Component، بل سيبحث أيضًا عن جميع التعليقات التوضيحية الأخرى الموروثة من هذه التعليقات التوضيحية. على سبيل المثال، @Controllerو @RestController، و @Service، @Repositoryوغيرها، والتي سنلتقي بها في مقالات لاحقة. الآن دعونا نحاول أن نفعل الشيء نفسه، ولكن باستخدام تكوين جافا . أولاً، دعونا نزيل التعليقات التوضيحية @Componentمن فصولنا الدراسية. ولتعقيد المهمة، دعونا نتخيل أن هذه ليست فصول دراسية مكتوبة بأنفسنا، والتي يمكننا تعديلها بسهولة، وإضافة شيء ما، بما في ذلك التعليقات التوضيحية. يبدو الأمر كما لو أن هذه الفصول الدراسية معبأة في بعض المكتبات. في هذه الحالة، لا يمكننا تعديل هذه الفئات بأي شكل من الأشكال حتى يتم قبولها بحلول الربيع. لكننا بحاجة إلى كائنات من هذه الفئات! سنحتاج هنا إلى تكوين Java لإنشاء مثل هذه الكائنات. للبدء، لنقم بإنشاء حزمة، على سبيل المثال configs، وفيها - فئة Java عادية، على سبيل المثال، MyConfigووضع علامة عليها بتعليق توضيحي@Configuration
@Configuration
public class MyConfig {
}
نحتاج الآن إلى تعديل main()الطريقة التي ننشئ بها السياق في الطريقة قليلاً. يمكننا إما تحديد فئتنا مباشرةً من خلال التكوين هناك:
ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class);
إذا كان لدينا عدة فئات مختلفة حيث نقوم بإنشاء وحدات ونريد ربط العديد منها في وقت واحد، فإننا ببساطة نشير إليها مفصولة بفواصل:
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، مما يعني أن هذه الأساليب ستعيد الفاصوليا (الكائنات) التي وضعتها بالفعل في سياقها. حسنًا، لنقم الآن بإنشاء فاصوليا للقطط والكلاب والببغاء في فصلنا باستخدام تكوين Java. ويتم ذلك بكل بساطة:
@Bean
public Cat getCat() {
	return new Cat();
}
اتضح أننا أنشأنا قطتنا يدويًا بأنفسنا وأعطيناها لـ Spring، وقد وضع بالفعل هذا الكائن الخاص بنا في سياقه. نظرًا لأننا لم نحدد اسم حبوبنا بشكل صريح، فسيعطي Spring للفاصوليا نفس اسم اسم الطريقة. في حالتنا، سيكون لفاصوليا القطة اسم " getCat". ولكن بما أنه في main-e ما زلنا نحصل على القطة ليس بالاسم، ولكن حسب الفئة، ففي هذه الحالة اسم هذا الصندوق ليس مهمًا بالنسبة لنا. اصنع حبة مع كلب بنفس الطريقة، لكن ضع في اعتبارك أن Spring سيسمي هذه الحبة باسم الطريقة. لتسمية الفول الخاص بنا بشكل صريح مع الببغاء، ما عليك سوى الإشارة إلى اسمه بين قوسين بعد الشرح @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. بالإضافة إلى ذلك، يتيح لك تكوين Java تنفيذ أي تعليمات برمجية Java على الإطلاق في طرق إنشاء الحبوب. يمكنك حقًا فعل أي شيء: إنشاء كائنات مساعدة أخرى، واستدعاء أي طرق أخرى، حتى تلك التي لم يتم تمييزها بتعليقات توضيحية زنبركية، وإنشاء حلقات، وشروط - كل ما يتبادر إلى ذهنك! لا يمكن تحقيق كل هذا باستخدام التكوين التلقائي، ناهيك عن استخدام تكوينات XML. الآن دعونا نلقي نظرة على مشكلة أكثر متعة. مع تعدد الأشكال والواجهات :) لنقم بإنشاء واجهة WeekDayوإنشاء 7 فئات من شأنها تنفيذ هذه الواجهة: 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 في سياقه ليرى أيًا من حبوبه تنفذ مثل هذه الواجهة وسيعيدها. حسنًا، اتضح أن WeekDayهناك كائنًا من النوع في متغير من النوع Sunday، وتعدد الأشكال، المألوف لنا جميعًا، يبدأ عند العمل مع هذا المتغير. :) وبضع كلمات حول النهج المشترك ، حيث يتم إنشاء بعض الحبوب بواسطة Spring نفسه، باستخدام مسح الحزم بحثًا عن وجود فئات مع تعليق توضيحي @Component، ويتم إنشاء بعض الحبوب الأخرى باستخدام تكوين Java. للقيام بذلك، دعنا نعود إلى الإصدار الأصلي، عندما تم تمييز Catالفئات بتعليق توضيحي . لنفترض أننا نريد إنشاء صناديق لحيواناتنا باستخدام المسح التلقائي للحزمة بحلول الربيع، ولكننا نرغب في إنشاء سلة تحتوي على يوم من أيام الأسبوع كما فعلنا للتو. كل ما عليك فعله هو الإضافة على مستوى الفصل ، والذي نحدده عند إنشاء السياق في التعليق التوضيحي -th ، والإشارة بين قوسين إلى الحزمة التي يجب فحصها وإنشاء وحدات الفئات الضرورية تلقائيًا: DogParrot@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" وإنشاء وحدات حبوب من تلك الفئات، وبعد ذلك ينفذ طريقة getDay()من الفئة MyConfigويضيف حبة من هذا النوع WeekDayإلى سياقه. في هذه الطريقة، main()أصبح لدينا الآن إمكانية الوصول إلى جميع الفاصوليا التي نحتاجها: كل من الكائنات الحيوانية وفاصوليا يوم الأسبوع. كيفية التأكد من أن Spring يلتقط أيضًا بعض تكوينات XML - ابحث عنها على الإنترنت بنفسك إذا كنت في حاجة إليها :) الملخص:
  • حاول استخدام التكوين التلقائي.
  • أثناء التكوين التلقائي، نشير إلى اسم الحزمة التي تحتوي على الفئات التي يجب إنشاء وحداتها؛
  • يتم تمييز هذه الفئات بتعليق توضيحي@Component;
  • يمر الربيع بجميع هذه الفئات وينشئ كائناتها ويضعها في السياق؛
  • إذا كان التكوين التلقائي لا يناسبنا لسبب ما، فإننا نستخدم تكوين جافا؛
  • في هذه الحالة، نقوم بإنشاء فئة Java عادية والتي ستعيد طرقها الكائنات التي نحتاجها، ونضع علامة على هذه الفئة بتعليق توضيحي @Configurationفي حالة فحصنا الحزمة بأكملها بدلاً من تحديد فئة معينة مع التكوين عند إنشاء السياق؛
  • يتم وضع علامة على أساليب هذه الفئة التي تقوم بإرجاع الحبوب مع التعليق التوضيحي @Bean؛
  • إذا أردنا تمكين المسح التلقائي عند استخدام تكوين جافا، فإننا نستخدم التعليق التوضيحي @ComponentScan.
إذا لم يكن هناك شيء واضح، فحاول قراءة هذه المقالة في غضون يومين. حسنًا، أو إذا كنت في المستويات المبكرة من جافاراش، فربما يكون من المبكر جدًا أن تتعلم الربيع. يمكنك دائمًا العودة إلى هذه المقالة بعد قليل، عندما تشعر بثقة أكبر في البرمجة بلغة Java. إذا كان كل شيء واضحًا، فيمكنك محاولة نقل بعض مشاريع الحيوانات الأليفة الخاصة بك إلى الربيع :) إذا كان هناك شيء واضح، ولكن هناك شيء ليس كثيرًا، فيرجى التعليق :) هناك أيضًا اقتراحات وتعليقات إذا ذهبت إلى مكان ما أو كتبت شيئًا غبيًا ) في المقالة التالية سوف نتعمق في Spring-web-mvc ونقوم بإنشاء تطبيق ويب بسيط باستخدام Spring.
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION