CodeGym /Blog Java /Ngẫu nhiên /Spring for lazy people Nền tảng, khái niệm cơ bản và ví d...
John Squirrels
Mức độ
San Francisco

Spring for lazy people Nền tảng, khái niệm cơ bản và ví dụ về mã. Phần 2

Xuất bản trong nhóm
Trong bài viết trước , tôi đã giải thích ngắn gọn Spring là gì, bean và bối cảnh là gì. Bây giờ là lúc để thử nó. Tôi sẽ làm điều đó bằng 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 IntelliJ IDEA miễn phí. Trong ảnh chụp màn hình, nếu bạn thấy rằng tôi có một số cửa sổ mà bạn không có, đừng lo lắng — điều đó không quan trọng đối với dự án này :) Spring for lazy people Nền tảng, khái niệm cơ bản và ví dụ về mã.  Phần 2 - 1Trước tiên, hãy tạo một dự án Maven trống. Tôi đã chỉ ra cách thực hiện việc này trong bài viết tại liên kết này . Đọc đến dòng chữ " Đã đến lúc chúng ta chuyển đổi dự án Maven của mình thành dự án web. " — sau đó, bài viết hướng dẫn cách tạo dự án web, nhưng hiện tại chúng ta không cần điều đó. Trong src/main/javathư mục, tạo một gói (trong trường hợp của tôi, tôi gọi nó là " en.codegym.info.fatfaggy.animals. Bạn có thể gọi nó là bất cứ thứ gì bạn muốn. Đừng quên thay thế tên gói của tôi bằng tên gói của bạn ở tất cả các vị trí phù hợp. Bây giờ hãy tạo lớp Mainvà thêm một phương pháp

public static void main(String[] args) {
    ...
}
Sau đó, mở tệp pom.xml và thêm dependenciesphần. Bây giờ hãy truy cập kho lưu trữ Maven và tìm bối cảnh Spring cho phiên bản ổn định mới nhất. Đặt những gì chúng tôi tìm thấy vào dependenciesphần này. Tôi đã mô tả quy trình này chi tiết hơn trong bài viết khác của CodeGym này (xem phần có tiêu đề " Kết nối các phần phụ thuộc trong Maven "). Sau đó, Maven sẽ tự tìm và tải xuống các phụ thuộc cần thiết. Cuối cùng, bạn sẽ nhận được kết quả như sau: Spring for lazy people Nền tảng, khái niệm cơ bản và ví dụ về mã.  Phần 2 - 2Trong cửa sổ bên trái, bạn có thể thấy cấu trúc dự án với gói và lớp Main. Cửa sổ ở giữa hiển thị cách pom.xml tìm kiếm tôi. Tôi cũng đã thêm một thuộc tínhphần cho nó. Phần này cho Maven biết tôi đang sử dụng phiên bản Java nào trong các tệp nguồn của mình và phiên bản nào sẽ biên dịch. Điều này chỉ để IDEA không cảnh báo tôi rằng tôi đang sử dụng phiên bản Java cũ. Đây là tùy chọn :) Cửa sổ bên phải cho thấy rõ rằng mặc dù chúng ta chỉ kết nối mô-đun spring-context, nhưng nó sẽ tự động kéo các mô-đun spring-core, spring-bean, spring-aop và spring-expression vào. Chúng tôi có thể đã kết nối riêng từng mô-đun, viết ra phần phụ thuộc cho từng mô-đun với phiên bản rõ ràng trong tệp pom.xml, nhưng hiện tại chúng tôi hài lòng với mọi thứ như hiện tại. Bây giờ hãy tạo entitiesgói và tạo 3 lớp trong đó: Cat, Dog, Parrot. Hãy đặt tên cho mỗi con vật (private String name- bạn có thể mã hóa cứng một số giá trị ở đó). Getters/setters là công khai. Bây giờ chúng ta chuyển sang Mainlớp và main()phương thức, và chúng ta viết một cái gì đó như thế này:

public static void main(String[] args) {
	// Create an empty Spring context that will look for its own beans based on the annotations in the specified package
	ApplicationContext context = 
		new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.entities");

	Cat cat = context.getBean(Cat.class);
	Dog dog = (Dog) context.getBean("dog");
	Parrot parrot = context.getBean("parrot-polly", 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 ngữ cảnh, báo cho hàm tạo biết gói nào cần tìm để tìm các hạt đậu. Nói cách khác, 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 chú thích đặc biệt cho biết chúng là đậu. 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. Sau đó, chúng tôi nhận được một con mèo từ bối cảnh này. Chúng tôi gọi đối tượng ngữ cảnh để cung cấp cho chúng tôi một bean (đối tượng), chỉ ra lớp của đối tượng mà chúng tôi muốn (nhân tiện, chúng tôi cũng có thể chỉ định các giao diện, không chỉ các lớp). Sau đó, Spring trả về một đối tượng của lớp được yêu cầu, sau đó chúng ta lưu đối tượng này 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à "con chó". Khi mùa xuân tạo ra mộtDogđối tượng, nó cung cấp cho đối tượng một tên tiêu chuẩn (trừ khi bean được tạo đã được gán một tên rõ ràng), đó là tên lớp nhưng với một chữ cái viết thường ban đầu. Trong trường hợp này, lớp của chúng ta được gọi là Dog, vì vậy tên của bean là "dog". Nếu chúng ta cần một BufferedReaderđối tượng ở đó, thì Spring sẽ đặt tên nó là "bufferedReader". Và bởi vì Java không thể chắc chắn 100% lớp mà chúng ta muốn, nên nó trả về một Objectđối tượng, sau đó chúng ta sẽ chuyển sang loại mong muốn theo cách thủ công, tức làDog. Tùy chọn trong đó lớp được chỉ định rõ ràng sẽ thuận tiện hơn. Tùy chọn thứ ba là lấy một bean theo tên lớp và theo tên bean. Có thể bối cảnh có thể có một số đậu của một lớp. Để chỉ ra loại đậu cụ thể mà chúng ta cần, chúng ta chỉ ra tên của nó. Bởi vì chúng tôi cũng chỉ ra rõ ràng lớp ở đây, chúng tôi không còn phải thực hiện ép kiểu nữa. QUAN TRỌNG!Nếu Spring tìm thấy một số loại đậu phù hợp với yêu cầu của chúng tôi, thì nó không thể xác định loại đậu nào sẽ cung cấp cho chúng tôi, vì vậy nó sẽ đưa ra một ngoại lệ. Theo đó, để tránh tình trạng này, bạn nên cố gắng nói cho Spring biết loại đậu nào bạn cần càng cụ thể càng tốt. Nếu Spring tìm kiếm ngữ cảnh của nó và không tìm thấy một bean duy nhất phù hợp với yêu cầu của chúng tôi, thì nó cũng sẽ đưa ra một ngoại lệ. Cuối cùng, chúng tôi chỉ cần hiển thị tên của các con vật của mình để xác minh rằng chúng tôi thực sự có được những đồ vật mình cần. Nhưng nếu chúng ta chạy chương trình bây giờ, chúng ta sẽ thấy rằng Spring không vui — nó không thể tìm thấy những con vật chúng ta cần trong ngữ cảnh của nó. Điều này là do nó chưa tạo ra những hạt đậu này. Như tôi đã nói trước đây, khi Spring quét các lớp, nó sẽ tìm các chú thích Spring của chính nó. Và nếu Spring không tìm thấy những chú thích này, thì nó sẽ không t nghĩ rằng các lớp này tương ứng với các bean mà nó cần tạo. Khắc phục điều này chỉ cần thêm@Componentchú thích trước mỗi lớp động vật của chúng tôi.

@Component
public class Cat {
	private String name = "Oscar";
	...
}
Nhưng có nhiều hơn nữa. Nếu chúng ta cần nói rõ ràng với Spring rằng bean cho lớp này phải có một tên cụ thể, chúng ta sẽ chỉ ra tên đó trong ngoặc đơn sau chú thích. Ví dụ, để yêu cầu Spring đặt tên " parrot-polly" cho vẹt bean, là tên mà chúng ta sẽ sử dụng để lấy con vẹt này trong mainphương thức, chúng ta nên làm như sau:

@Component("parrot-polly")
public class Parrot {
	private String name = "Polly";
	...
}
Đây là toàn bộ đ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à báo cho Spring biết gói chứa các lớp của bạn. Đây là gói mà framework sẽ chạy qua để tìm các chú thích và tạo các đối tượng của các lớp này. Nhân tiện, Spring không chỉ tìm kiếm @Componentcác chú thích mà còn tìm kiếm tất cả các chú thích khác kế thừa chú thích này. Ví dụ: , @Controller, @RestController, @Service, @Repositoryv.v. mà chúng tôi sẽ giới thiệu trong các bài viết sau. Bây giờ chúng ta sẽ thử làm điều tương tự bằng cách sử dụng cấu hình dựa trên Java . Để bắt đầu, hãy xóa@Componentchú thích từ các lớp học của chúng tôi. Để làm cho mọi thứ trở nên khó khăn hơn, hãy tưởng tượng rằng chúng tôi không viết các lớp này, vì vậy chúng tôi không thể dễ dàng sửa đổi chúng, điều đó có nghĩa là chúng tôi không thể thêm chú thích. Nó giống như những lớp này được đóng gói trong một thư viện nào đó. Trong trường hợp này, không có cách nào để chúng ta chỉnh sửa các lớp này để Spring nhận ra chúng. Nhưng chúng ta cần các đối tượng của các lớp này! Ở đây chúng ta cần cấu hình dựa trên Java để tạo các đối tượng. Để bắt đầu, hãy tạo một gói có tên như configs. Trong gói này, hãy tạo một lớp Java thông thường, chẳng hạn như MyConfig, và đánh dấu nó bằng @Configurationchú thích.

@Configuration
public class MyConfig {
}
Bây giờ chúng ta cần điều chỉnh main()phương thức, thay đổi cách chúng ta tạo bối cảnh. Chúng tôi có thể chỉ ra rõ ràng lớp nào có cấu hình của chúng tôi:

ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class);
Nếu chúng ta có một số lớp khác nhau tạo ra các hạt đậu và chúng ta muốn kết nối đồng thời nhiều lớp trong số chúng, thì chúng ta chỉ cần chỉ ra tất cả chúng ở đó, được phân tách bằng dấu phẩy:

ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class, MyAnotherConfig.class);
Và 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, thì chúng tôi chỉ cần cho biết tên của gói chứa chúng:

ApplicationContext context =
	new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.configs");
Trong trường hợp này, Spring sẽ duyệt qua gói và tìm tất cả các lớp được đánh dấu bằng @Configurationchú thích. Chà, và nếu 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, thì chúng ta chỉ cần chỉ ra một danh sách tên của các gói chứa cấu hình được phân tách bằng dấu phẩy:

ApplicationContext context =
	new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.database.configs",
		"en.codegym.info.fatfaggy.animals.root.configs",
		"en.codegym.info.fatfaggy.animals.web.configs");
Hoặc tên của một gói chung cho tất cả chúng:

ApplicationContext context =
	new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals");
Bạn có thể làm điều đó theo cách bạn muốn, nhưng đối với tôi, có vẻ như tùy chọn đầu tiên, chỉ đơn giản chỉ ra 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 tìm kiếm các lớp được đánh dấu bằng @Configurationchú thích và sẽ tạo các đối tượng riêng của các lớp này. Nó cố gắng gọi các phương thức được đánh dấu bằng @Beanchú thích, nghĩa là các phương thức này trả về các bean (đối tượng) mà Spring sẽ thêm vào ngữ cảnh. Và bây giờ chúng ta sẽ tạo các hạt đậu cho một con mèo, con chó và con vẹt trong lớp của chúng ta với cấu hình dựa trên Java. Điều này là khá đơn giản để làm:

@Bean
public Cat getCat() {
	return new Cat();
}
Ở đây, chúng tôi tạo thủ công con mèo của mình và giao nó cho Spring, sau đó giữ đối tượng của chúng tôi trong ngữ cảnh của nó. Vì chúng ta không đặt tên rõ ràng cho bean của mình, nên Spring sẽ đặt tên cho nó giống với tên của phương thức. Trong trường hợp của chúng tôi, hạt đậu mèo sẽ được gọi là " getCat". Nhưng bởi vì chúng ta sử dụng lớp chứ không phải tên, để lấy cat bean trong phương mainthức, nên tên của bean không quan trọng đối với chúng ta. Tương tự, tạo một dog bean, lưu ý rằng Spring sẽ đặt tên phương thức cho bean. Để đặt tên rõ ràng cho hạt vẹt của chúng tôi, chúng tôi chỉ cần chỉ ra tên của nó trong ngoặc đơn sau chú @Beanthích:

@Bean("parrot-polly")
public Object weNeedMoreParrots() {
	return new Parrot();
}
Như bạn có thể thấy, ở đây tôi đã chỉ ra một Objectkiểu trả về và đặt tên tùy ý cho phương thức. Điều này không ảnh hưởng đến tên của hạt đậu, bởi vì chúng tôi đã chỉ định rõ ràng tên ở đây. Tuy nhiên, tốt hơn là chỉ ra một giá trị trả về và tên phương thức ít nhiều có ý nghĩa. Làm điều này nếu không vì lý do nào khác ngoài việc giúp đỡ bản thân khi bạn mở lại dự án sau một năm. :) Bây giờ hãy xem xét tình huống mà chúng ta cần một hạt đậu để tạo một hạt đậu khác . Ví dụ: giả sử chúng ta muốn tên của con mèo trong hạt đậu mèo là tên của con vẹt cộng với 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 để tạo bean này, framework cần phải truyền vào vẹt bean đã tạo trước đó. Theo đó, nó sẽ sắp xếp chuỗi lệnh gọi phương thức cần thiết: đầu tiên, phương thức tạo con vẹt được gọi và sau đó khung chuyển con vẹt mới sang phương thức tạo con mèo. Đây là nơi mà tính năng tiêm phụ thuộc phát huy tác dụng: Bản thân mùa xuân chuyển đậu con vẹt cần thiết cho phương thức của chúng ta. Nếu IDEA khó chịu về parrotbiến này, đừng quên thay đổi kiểu trả về của phương thức tạo con vẹt từ Objectthành Parrot. Ngoài ra, cấu hình dựa trên Java cho phép bạn chạy hoàn toàn bất kỳ mã Java nàotrong phương pháp tạo đậu của bạn. 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 Spring, tạo vòng lặp, điều kiện Boolean - bất cứ điều gì bạn nghĩ đến! Điều này không hoàn toàn khả thi với cấu hình tự động và thậm chí còn ít hơn với cấu hình XML. Bây giờ hãy xem xét một vấn đề thú vị hơn một chút. Tính đa hình và giao diện :) Chúng ta sẽ tạo một WeekDaygiao diện và tạo 7 lớp thực hiện giao diện này: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday. Chúng ta sẽ cung cấp cho giao diện một String getWeekDayName()phương thức, phương thức này sẽ trả về tên của ngày trong tuần cho lớp tương ứng. Nói cách khác, Mondaylớp sẽ trở lại "Monday", v.v. Khi khởi động ứng dụng, giả sử nhiệm vụ của chúng ta là đặt một bean tương ứng với ngày hiện tại trong tuần vào ngữ cảnh. Không phải bean cho tất cả các lớp triển khai giao diện — chỉ một bean mà chúng ta cần. Bạn có WeekDaythể làm điều đó 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 trả về là giao diện của chúng ta. Phương thức này trả về một đối tượng thực sự của một trong 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ờ chúng ta có thể làm như sau trong main()phương thức:

WeekDay weekDay = context.getBean(WeekDay.class);
System.out.println("Today is " + weekDay.getWeekDayName() + "!");
Đối với tôi, chương trình cho tôi biết hôm nay là Chủ nhật :) Tôi tự tin rằng nếu tôi chạy chương trình vào ngày mai, ngữ cảnh sẽ chứa một đối tượng hoàn toàn khác. Lưu ý rằng chúng tôi đang lấy bean chỉ bằng cách sử dụng giao diện: context.getBean(WeekDay.class). Spring sẽ tìm kiếm bean cài đặt giao diện trong ngữ cảnh của nó và sẽ trả về nó. Sau đó, hóa ra WeekDaybiến của chúng ta kết thúc bằng một đối tượng Sunday và khái niệm đa hình quen thuộc được áp dụng khi chúng ta làm việc với biến này. :) Bây giờ là một vài lời về cách tiếp cận kết hợp , trong đó một số bean được tạo tự động bởi Spring, một số bằng cách quét các gói cho các lớp có chú thích @Componentvà một số khác bằng cấu hình dựa trên Java. Khi chúng tôi xem xét điều này, chúng tôi sẽ quay lại phiên bản gốc, trong đó Cat, DogParrotcác lớp được đánh dấu bằng @Componentchú thích. Giả sử chúng ta muốn tạo bean cho các con vật của mình bằng cách để Spring tự động quét gói entities, nhưng chúng ta cũng muốn tạo một bean với ngày trong tuần, giống như chúng ta vừa làm. Tất cả những gì bạn cần làm là thêm @ComponentScanchú thích ở cấp độ của MyConfiglớp mà chúng tôi chỉ ra khi tạo ngữ cảnh trong main(), và chỉ ra trong ngoặc đơn gói cần được quét và tự động tạo các hạt của các lớp cần thiết:

@Configuration
@ComponentScan("en.codegym.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();
		}
	}
}
Khi tạo bối cảnh, Spring thấy rằng nó cần xử lý MyConfiglớp. Nó vào lớp và thấy rằng nó cần quét en.codegym.info.fatfaggy.animals.entitiesgói " " và tạo các bean của các lớp đó, sau đó nó thực thi phương thức MyConfigcủa lớp getDay()và thêm một WeekDaybean vào ngữ cảnh. Trong main()phương thức này, 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ả các đối tượng động vật và một loại đậu có ngày trong tuần. Nếu bạn cần làm cho Spring cũng chọn một số tệp cấu hình XML, bạn có thể thực hiện tìm kiếm trên web của riêng mình để tìm lời giải thích :) 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, hãy chỉ ra tên của gói chứa các lớp cần tạo hạt đậu
  • Các lớp này được đánh dấu bằng @Componentchú thích
  • Mùa xuân chạy qua tất cả các lớp này, tạo các đối tượ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 dựa trên Java
  • Trong trường hợp này, chúng ta tạo một lớp Java thông thường có các phương thức trả về các đối tượng chúng ta cần. Chúng tôi đánh dấu lớp này bằng @Configurationchú thích nếu chúng tôi sẽ quét toàn bộ gói thay vì chỉ ra một lớp cụ thể với 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 @Beanchú thích
  • Nếu chúng tôi muốn kích hoạt quét tự động khi sử dụng cấu hình dựa trên Java, chúng tôi sử dụng @ComponentScanchú thích.
Nếu bài viết này hoàn toàn khó hiểu, thì hãy thử đọc nó trong vài ngày tới. Hoặc nếu bạn đang ở một trong những cấp độ đầu tiên của CodeGym, có thể hơi sớm để bạn học Spring. Bạn luôn có thể quay lại bài viết này sau một thời gian ngắn khi bạn cảm thấy tự tin hơn về kỹ năng lập trình Java của mình. Nếu mọi thứ rõ ràng, thì bạn có thể thử chuyển đổi một số dự án thú cưng của mình thành Spring :) Nếu một số điều rõ ràng nhưng những điều khác thì không, vui lòng để lại nhận xét :) Hãy cho tôi biết các đề xuất và phê bình của bạn, nếu tôi sai ở đâu đó hoặc đã viết một số điều vô nghĩa :) Trong bài viết tiếp theo, chúng ta sẽ đột ngột đi sâu vào spring-web-mvc và tạo một ứng dụng web đơn giản bằng Spring.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION