JavaRush /Blog Java /Random-VI /Mùa xuân dành cho những kẻ lười biếng. Nguyên tắc cơ bản,...
Стас Пасинков
Mức độ
Киев

Mùa xuân dành cho những kẻ lười biếng. Nguyên tắc cơ bản, khái niệm cơ bản và ví dụ về mã. Phần 2

Xuất bản trong nhóm
Ở bài trước mình đã giải thích ngắn gọn lò xo là gì, thùng là gì và bối cảnh. Bây giờ là lúc để thử xem mọi thứ hoạt động như thế nào. Mùa xuân dành cho những kẻ lười biếng.  Nguyên tắc cơ bản, khái niệm cơ bản và ví dụ về mã.  Phần 2 - 1Tôi sẽ tự mình làm điều đó trong Intellij Idea Enterprise Edition. Nhưng tất cả các ví dụ của tôi cũng sẽ hoạt động trong Phiên bản cộng đồng ý tưởng Intellij miễn phí. Nếu bạn thấy trong ảnh chụp màn hình rằng tôi có một loại cửa sổ nào đó mà bạn không có, đừng lo lắng, nó không quan trọng đối với dự án này :) Trước tiên, hãy tạo một dự án Maven trống. Tôi đã hướng dẫn cách thực hiện điều này trong bài viết (đọc cho đến khi thấy dòng chữ “ Đã đến lúc biến dự án maven của chúng ta thành một dự án web. ”, sau đó nó đã hướng dẫn cách tạo một dự án web và bây giờ chúng ta không cần điều này) Hãy tạo nó trong thư mục src/main /java là một gói nào đó (trong trường hợp của tôi, tôi gọi nó là “ ru.javarush.info.fatfaggy.animals”, bạn có thể đặt tên gì tùy thích, chỉ cần đừng quên thay thế bằng tên của bạn vào đúng chỗ). Và hãy tạo một lớp Maintrong đó chúng ta sẽ tạo một phương thức
public static void main(String[] args) {
    ...
}
Sau đó mở tệp pom.xml và thêm một phần vào đó dependencies. Bây giờ chúng ta đi đến kho lưu trữ Maven và tìm bối cảnh mùa xuân của phiên bản ổn định mới nhất ở đó và dán những gì chúng ta có vào trong phần dependencies. Tôi đã mô tả quá trình này chi tiết hơn một chút trong bài viết này (xem phần " Kết nối các phụ thuộc trong Maven "). Sau đó, chính Maven sẽ tìm và tải xuống các phụ thuộc cần thiết và cuối cùng bạn sẽ nhận được một cái gì đó như thế này:
Mùa xuân dành cho những kẻ lười biếng.  Nguyên tắc cơ bản, khái niệm cơ bản và ví dụ về mã.  Phần 2 - 2
Trong cửa sổ bên trái, bạn có thể thấy cấu trúc của dự án với gói và lớp Main. Cửa sổ ở giữa hiển thị giao diện pom.xml của tôi. Tôi cũng đã thêm phần thuộc tính ở đó , trong đó tôi chỉ cho Maven biết tôi đang sử dụng phiên bản Java nào trong mã nguồn và phiên bản nào sẽ biên dịch thành. Điều này chỉ để tôi không có ý tưởng cảnh báo khi khởi động rằng một phiên bản Java cũ đang được sử dụng. Bạn có thể làm được, bạn không thể) Trong cửa sổ bên phải - bạn có thể thấy rằng mặc dù chúng tôi chỉ kết nối với ngữ cảnh mùa xuân - nó vẫn tự động thêm lõi, đậu, aop và biểu thức. Có thể kết nối từng mô-đun riêng biệt, đăng ký phần phụ thuộc cho từng mô-đun trong bộ nhớ với chỉ báo rõ ràng về phiên bản, nhưng hiện tại, chúng tôi hài lòng với tùy chọn như hiện tại. Bây giờ hãy tạo một gói entities(thực thể) và tạo 3 lớp trong đó: Cat, Dog, Parrot. Đặt cho mỗi con vật có một tên ( private String name, bạn có thể mã hóa cứng một số giá trị ở đó) và getters/setters là công khai. Bây giờ hãy đến lớp Mainmain()viết một cái gì đó như thế này trong phương thức:
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());
}
Đầu tiên, chúng ta tạo một đối tượng bối cảnh và trong hàm tạo, chúng ta đặt cho nó tên của gói cần được quét để tìm sự hiện diện của đậu. Tức là Spring sẽ duyệt qua gói này và cố gắng tìm các lớp được đánh dấu bằng các chú thích đặc biệt để Spring biết rằng đây là một Bean. Sau đó, nó tạo các đối tượng của các lớp này và đặt chúng vào ngữ cảnh của nó. Sau đó chúng ta có được một con mèo từ bối cảnh này. Khi xử lý đối tượng bối cảnh, chúng tôi yêu cầu nó cung cấp cho chúng tôi một Bean (đối tượng) và cho biết chúng tôi cần loại đối tượng nào (nhân tiện, ở đây, bạn có thể chỉ định không chỉ các lớp mà còn cả giao diện). Sau đó Spring trả về một đối tượng của lớp này cho chúng ta và chúng ta lưu nó vào một biến. Tiếp theo, chúng tôi yêu cầu Spring lấy cho chúng tôi một hạt đậu có tên là “dog”. Khi Spring tạo một đối tượng lớp, Dognó sẽ đặt cho nó một tên chuẩn (nếu tên của Bean được tạo không được chỉ định rõ ràng), đó là tên lớp của đối tượng, chỉ kèm theo một chữ cái nhỏ. Vì vậy, vì lớp của chúng ta được gọi là Dog, nên tên của loại đậu đó sẽ là “dog”. Nếu chúng ta có một đối tượng ở đó BufferedReaderthì Spring sẽ đặt tên mặc định cho nó là “bufferedReader”. Và vì trong trường hợp này (trong Java) không có sự chắc chắn chính xác về lớp đối tượng đó sẽ là gì, nên chỉ cần trả về một đối tượng nhất định Object, sau đó chúng tôi chuyển thủ công sang loại chúng tôi cần Dog. Tùy chọn có chỉ dẫn rõ ràng về lớp sẽ thuận tiện hơn. Chà, trong trường hợp thứ ba, chúng ta nhận được một hạt đậu theo lớp và tên. Có thể đơn giản là có một tình huống trong ngữ cảnh sẽ có một số loại đậu thuộc một lớp và để chỉ ra loại đậu cụ thể nào chúng ta cần, chúng ta chỉ ra tên của nó. Vì chúng tôi cũng đã chỉ rõ lớp học ở đây nên chúng tôi không cần phải chọn nữa. Quan trọng!Nếu Spring tìm thấy một số loại đậu theo yêu cầu mà chúng tôi đã chỉ định cho nó, nó sẽ không thể xác định loại đậu nào sẽ cung cấp cho chúng tôi và sẽ đưa ra một ngoại lệ. Vì vậy, hãy cố gắng chỉ cho anh ấy biết chính xác nhất có thể bạn cần loại thùng nào để không xảy ra những tình huống như vậy. Nếu Spring không tìm thấy một hạt đậu nào trong ngữ cảnh của nó theo điều kiện của bạn, nó cũng sẽ đưa ra một ngoại lệ. Chà, sau đó chúng ta chỉ cần hiển thị tên các con vật của mình trên màn hình để đảm bảo rằng đây thực sự chính xác là những đồ vật mà chúng ta cần. Nhưng nếu chạy chương trình bây giờ, chúng ta sẽ thấy Spring đang thề rằng nó không thể tìm thấy những con vật chúng ta cần trong bối cảnh của nó. Điều này xảy ra bởi vì anh ấy không tạo ra những hạt đậu này. Như tôi đã nói, khi Spring quét các lớp, nó sẽ tìm các chú thích Spring “của nó” ở đó. Và nếu nó không tìm thấy nó, thì nó sẽ không nhận biết được những lớp mà anh ta cần tạo ra những lớp đậu. Để khắc phục điều này, chỉ cần thêm chú thích @Componentở phía trước lớp trong lớp động vật của chúng ta.
@Component
public class Cat {
	private String name = "Barsik";
	...
}
Nhưng đó không phải là tất cả. Nếu chúng ta cần chỉ rõ cho Spring rằng Bean của lớp này phải có một tên cụ thể thì tên này có thể được chỉ định trong ngoặc đơn sau chú thích. Ví dụ, để Spring đặt tên cho parrot-keshacon vẹt mà chúng ta cần, từ đó chúng ta mainsẽ nhận được con vẹt này sau này, chúng ta cần làm một cái gì đó như thế này:
@Component("parrot-kesha")
public class Parrot {
	private String name = "Kesha";
	...
}
Đây là toàn bộ quan điểm của cấu hình tự động . Bạn viết các lớp của mình, đánh dấu chúng bằng các chú thích cần thiết và chỉ ra cho Spring một gói có các lớp của bạn, qua đó nó sẽ tìm kiếm các chú thích và tạo các đối tượng của các lớp đó. Nhân tiện, Spring sẽ không chỉ tìm kiếm các chú thích @Componentmà còn tìm kiếm tất cả các chú thích khác được kế thừa từ chú thích này. Ví dụ: @Controller, @RestController, và những thứ khác @Service@Repositorychúng ta sẽ gặp trong các bài viết tiếp theo. Bây giờ chúng ta hãy thử làm tương tự nhưng sử dụng cấu hình java . Đầu tiên, hãy xóa chú thích @Componentkhỏi các lớp của chúng ta. Để làm phức tạp nhiệm vụ, hãy tưởng tượng rằng đây không phải là các lớp tự viết của chúng ta, mà chúng ta có thể dễ dàng sửa đổi, thêm nội dung nào đó, bao gồm cả chú thích. Cứ như thể những lớp này được gói gọn trong một thư viện nào đó. Trong trường hợp này, chúng tôi không thể chỉnh sửa các lớp này theo bất kỳ cách nào để chúng được chấp nhận vào mùa xuân. Nhưng chúng ta cần các đối tượng của các lớp này! Ở đây chúng ta sẽ cần cấu hình java để tạo các đối tượng như vậy. Để bắt đầu, hãy tạo một gói, chẳng hạn configs, và trong đó - một lớp Java thông thường chẳng hạn, MyConfigvà đánh dấu nó bằng một chú thích@Configuration
@Configuration
public class MyConfig {
}
Bây giờ chúng ta cần điều chỉnh một chút main()cách chúng ta tạo bối cảnh trong phương thức. Chúng ta có thể chỉ định trực tiếp lớp của mình với cấu hình ở đó:
ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class);
Nếu chúng ta có một số lớp khác nhau nơi chúng ta tạo các hạt đậu và muốn kết nối nhiều lớp trong số chúng cùng một lúc, chúng ta chỉ cần chỉ ra chúng được phân tách bằng dấu phẩy:
ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class, MyAnotherConfig.class);
Chà, nếu chúng tôi có quá nhiều trong số chúng và chúng tôi muốn kết nối tất cả chúng cùng một lúc, chúng tôi chỉ cần chỉ ra ở đây tên của gói mà chúng tôi có chúng:
ApplicationContext context =
	new AnnotationConfigApplicationContext("ru.javarush.info.fatfaggy.animals.configs");
Trong trường hợp này, Spring sẽ duyệt qua gói này và tìm tất cả các lớp được đánh dấu bằng chú thích @Configuration. Chà, trong trường hợp chúng ta có một chương trình thực sự lớn trong đó các cấu hình được chia thành các gói khác nhau, chúng ta chỉ cần chỉ ra tên của các gói bằng các cấu hình được phân tách bằng dấu phẩy:
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");
Chà, hoặc tên của một gói phổ biến hơn đối với tất cả chúng:
ApplicationContext context =
	new AnnotationConfigApplicationContext("ru.javarush.info.fatfaggy.animals");
Bạn có thể làm điều đó theo ý muốn, nhưng đối với tôi, có vẻ như tùy chọn đầu tiên, trong đó bạn chỉ cần chỉ định một lớp có cấu hình, sẽ phù hợp nhất với chương trình của chúng tôi. Khi tạo ngữ cảnh, Spring sẽ tìm kiếm các lớp được đánh dấu bằng chú thích @Configurationvà tự tạo đối tượng của các lớp này. Sau đó, nó sẽ cố gắng gọi các phương thức trong các lớp được đánh dấu bằng chú thích này @Bean, có nghĩa là các phương thức đó sẽ trả về các đậu (đối tượng) mà nó đã đặt trong ngữ cảnh của nó. Bây giờ chúng ta hãy tạo đậu mèo, chó và vẹt trong lớp của chúng ta với cấu hình java. Việc này được thực hiện khá đơn giản:
@Bean
public Cat getCat() {
	return new Cat();
}
Hóa ra là chúng tôi đã tự tạo ra con mèo của mình và đưa nó cho Spring, và anh ấy đã đặt đối tượng này của chúng tôi vào bối cảnh của mình. Vì chúng ta không chỉ định rõ ràng tên của Bean nên Spring sẽ đặt tên cho Bean giống với tên của phương thức. Trong trường hợp của chúng ta, hạt đậu mèo sẽ có tên " getCat". Nhưng vì trong main-e, chúng ta vẫn lấy con mèo không phải theo tên mà theo lớp, nên trong trường hợp này, tên của thùng này không quan trọng đối với chúng ta. Tạo một hạt đậu với một con chó theo cách tương tự, nhưng hãy nhớ rằng Spring sẽ đặt tên cho hạt đậu đó theo tên của phương thức. Để đặt tên rõ ràng cho hạt đậu của chúng ta là con vẹt, chỉ cần chỉ ra tên của nó trong ngoặc đơn sau chú thích @Bean:
@Bean("parrot-kesha")
public Object weNeedMoreParrots() {
	return new Parrot();
}
Như bạn có thể thấy, ở đây tôi đã chỉ ra loại giá trị trả về Objectvà gọi phương thức này là bất cứ thứ gì. Điều này không ảnh hưởng đến tên của đậu theo bất kỳ cách nào vì chúng tôi đã đặt nó một cách rõ ràng ở đây. Nhưng tốt hơn hết là bạn nên chỉ ra loại giá trị trả về và tên phương thức không phải là hiển nhiên mà ít nhiều rõ ràng. Ngay cả đối với chính bạn, khi bạn mở dự án này trong một năm. :) Bây giờ hãy xem xét tình huống để tạo một hạt đậu, chúng ta cần sử dụng một hạt đậu khác . Ví dụ: chúng tôi muốn tên của con mèo trong hạt mèo bao gồm tên của con vẹt và chuỗi "-killer". Không có gì!
@Bean
public Cat getCat(Parrot parrot) {
	Cat cat = new Cat();
	cat.setName(parrot.getName() + "-killer");
	return cat;
}
Ở đây Spring sẽ thấy rằng trước khi tạo ra hạt đậu này, anh ta sẽ cần chuyển hạt đậu vẹt đã được tạo ra ở đây. Vì vậy, anh ta sẽ xây dựng một chuỗi các lệnh gọi đến các phương thức của chúng ta để phương thức tạo một con vẹt được gọi trước, sau đó chuyển con vẹt này sang phương thức tạo một con mèo. Đây là nơi mà tính năng tiêm phụ thuộc hoạt động : Bản thân Spring đã chuyển đậu vẹt cần thiết vào phương pháp của chúng tôi. Nếu ý tưởng phàn nàn về một biến parrot, đừng quên thay đổi kiểu trả về trong phương thức tạo một con vẹt từ Objectthành Parrot. Ngoài ra, cấu hình Java cho phép bạn thực thi hoàn toàn bất kỳ mã Java nào trong các phương thức tạo đậu. Bạn thực sự có thể làm bất cứ điều gì: tạo các đối tượng phụ trợ khác, gọi bất kỳ phương thức nào khác, ngay cả những phương thức không được đánh dấu bằng chú thích mùa xuân, tạo vòng lặp, điều kiện - bất cứ điều gì bạn nghĩ đến! Tất cả điều này không thể đạt được bằng cách sử dụng cấu hình tự động, càng không thể sử dụng cấu hình xml. Bây giờ chúng ta hãy xem xét một vấn đề thú vị hơn. Với tính đa hình và giao diện :) Hãy tạo một giao diện WeekDayvà tạo 7 lớp sẽ triển khai giao diện này: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday. Hãy tạo một phương thức trong giao diện String getWeekDayName()sẽ trả về tên ngày trong tuần của lớp tương ứng. Nghĩa là, lớp Mondaysẽ trả về " monday", v.v. Giả sử nhiệm vụ khi khởi chạy ứng dụng của chúng ta là đặt một hạt đậu vào ngữ cảnh tương ứng với ngày hiện tại trong tuần. Không phải tất cả các đậu của tất cả các lớp đều triển khai WeekDaygiao diện mà chỉ có loại chúng ta cần. Nó có thể được thực hiện một cái gì đó như thế này:
@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();
	}
}
Ở đây, kiểu giá trị trả về là giao diện của chúng ta và phương thức trả về các đối tượng thực của các lớp triển khai giao diện tùy thuộc vào ngày hiện tại trong tuần. Bây giờ trong phương pháp main()chúng ta có thể làm điều này:
WeekDay weekDay = context.getBean(WeekDay.class);
System.out.println("It's " + weekDay.getWeekDayName() + " today!");
Nó nói với tôi rằng hôm nay là Chủ nhật :) Tôi chắc chắn rằng nếu tôi chạy chương trình vào ngày mai, một đối tượng hoàn toàn khác sẽ xuất hiện trong ngữ cảnh. Xin lưu ý rằng ở đây chúng ta lấy Bean đơn giản bằng giao diện: context.getBean(WeekDay.class). Spring sẽ xem xét ngữ cảnh của nó để xem hạt đậu nào của nó thực hiện giao diện như vậy và sẽ trả về giao diện đó. Chà, hóa ra là WeekDaycó một đối tượng thuộc loại trong một biến thuộc loại Sundayvà tính đa hình, vốn đã quen thuộc với tất cả chúng ta, bắt đầu khi làm việc với biến này. :) Và một vài lời về cách tiếp cận kết hợp , trong đó một số đậu được tạo bởi chính Spring, sử dụng chức năng quét các gói để tìm sự hiện diện của các lớp có chú thích @Componentvà một số đậu khác được tạo bằng cách sử dụng cấu hình java. Để làm điều này, chúng ta hãy quay lại phiên bản gốc, khi các lớp Catvà được Dogđánh Parrotdấu bằng chú thích @Component. Giả sử chúng ta muốn tạo các thùng cho động vật của mình bằng cách sử dụng chức năng quét tự động gói hàng entitiesvào mùa xuân, nhưng hãy tạo một thùng có ngày trong tuần như chúng ta vừa làm. Tất cả những gì bạn cần làm là thêm ở cấp độ lớp MyConfigmà chúng tôi chỉ định khi tạo ngữ cảnh trong mainchú thích -th @ComponentScanvà chỉ ra trong ngoặc gói cần được quét và các hạt của các lớp cần thiết được tạo tự động:
@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();
		}
	}
}
Hóa ra khi tạo ngữ cảnh, Spring thấy cần xử lý lớp MyConfig. Anh ta vào đó và thấy rằng anh ta cần quét gói " ru.javarush.info.fatfaggy.animals.entities" và tạo các đậu của các lớp đó, sau đó anh ta thực thi một phương thức getDay()từ lớp đó MyConfigvà thêm một loại đậu WeekDayvào ngữ cảnh của mình. Trong phương pháp này, main()bây giờ chúng ta có quyền truy cập vào tất cả các loại đậu mà chúng ta cần: cả đối tượng động vật và đậu ngày trong tuần. Làm cách nào để đảm bảo rằng Spring cũng chọn một số cấu hình xml - hãy tự tìm trên Internet nếu bạn cần :) Tóm tắt:
  • cố gắng sử dụng cấu hình tự động;
  • trong quá trình cấu hình tự động, chúng tôi chỉ ra tên của gói chứa các lớp có đậu cần được tạo;
  • các lớp như vậy được đánh dấu bằng chú thích@Component;
  • mùa xuân đi qua tất cả các lớp như vậy và tạo ra các đối tượng của chúng và đặt chúng vào ngữ cảnh;
  • nếu vì lý do nào đó cấu hình tự động không phù hợp với chúng tôi, chúng tôi sử dụng cấu hình java;
  • trong trường hợp này, chúng tôi tạo một lớp Java thông thường có các phương thức sẽ trả về các đối tượng chúng tôi cần và đánh dấu lớp đó bằng chú thích @Configurationtrong trường hợp chúng tôi quét toàn bộ gói thay vì chỉ định một lớp cụ thể có cấu hình khi tạo ngữ cảnh;
  • các phương thức của lớp này trả về các hạt đậu được đánh dấu bằng chú thích @Bean;
  • nếu chúng tôi muốn bật tính năng quét tự động khi sử dụng cấu hình java, chúng tôi sử dụng chú thích @ComponentScan.
Nếu không có gì rõ ràng thì hãy thử đọc bài viết này sau vài ngày nữa. Chà, hoặc nếu bạn đang ở cấp độ đầu tiên của Javarash, thì có lẽ còn hơi sớm để bạn học mùa xuân. Bạn luôn có thể quay lại bài viết này sau khi cảm thấy tự tin hơn khi lập trình bằng Java. Nếu mọi thứ đã rõ ràng, bạn có thể thử chuyển một số dự án yêu thích của mình sang Spring :) Nếu có điều gì đó rõ ràng nhưng có điều gì đó không quá nhiều, vui lòng bình luận :) Ngoài ra còn có những gợi ý và nhận xét nếu tôi bước đi đâu đó hoặc tôi đã viết điều gì đó ngu ngốc ) Trong bài viết tiếp theo, chúng ta sẽ đi sâu vào spring-web-mvc và tạo một ứng dụng web đơn giản bằng cách sử dụng spring.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION