JavaRush /Java Blog /Random-ID /Musim semi adalah untuk mereka yang malas. Dasar-dasar, k...
Стас Пасинков
Level 26
Киев

Musim semi adalah untuk mereka yang malas. Dasar-dasar, konsep dasar dan contoh dengan kode. Bagian 2

Dipublikasikan di grup Random-ID
Pada artikel terakhir saya menjelaskan secara singkat apa itu pegas, apa itu bin, dan konteksnya. Sekarang saatnya mencoba cara kerjanya. Musim semi adalah untuk mereka yang malas.  Dasar-dasar, konsep dasar dan contoh dengan kode.  Bagian 2 - 1Saya akan melakukannya sendiri di Intellij Idea Enterprise Edition. Namun semua contoh saya juga dapat digunakan di Intellij Idea Community Edition gratis. Hanya jika Anda melihat di tangkapan layar saya memiliki semacam jendela yang tidak Anda miliki, jangan khawatir, ini tidak penting untuk proyek ini :) Pertama, mari buat proyek Maven yang kosong. Cara melakukannya saya tunjukkan di artikel (baca sampai muncul tulisan “ Saatnya mengubah proyek maven kita menjadi proyek web. ”, setelah itu sudah ditampilkan cara membuat proyek web, dan kita tidak memerlukannya sekarang) Mari kita buat di folder src/main /java beberapa paket (dalam kasus saya, saya menyebutnya “ ru.javarush.info.fatfaggy.animals”, Anda dapat menamainya sesuka Anda, jangan lupa menggantinya dengan nama Anda di tempat yang tepat). Dan mari kita buat sebuah kelas Maindi mana kita akan membuat sebuah metode
public static void main(String[] args) {
    ...
}
Kemudian buka file pom.xml dan tambahkan bagian di sana dependencies. Sekarang kita pergi ke repositori Maven dan mencari konteks pegas dari versi stabil terbaru di sana, dan menempelkan apa yang kita dapatkan di dalam bagian tersebut dependencies. Saya menjelaskan proses ini lebih detail di artikel ini (lihat bagian " Menghubungkan dependensi di Maven "). Kemudian Maven sendiri akan menemukan dan mengunduh dependensi yang diperlukan, dan pada akhirnya Anda akan mendapatkan sesuatu seperti ini:
Musim semi adalah untuk mereka yang malas.  Dasar-dasar, konsep dasar dan contoh dengan kode.  Bagian 2 - 2
Di jendela kiri Anda dapat melihat struktur proyek dengan paket dan kelasnya Main. Jendela tengah menunjukkan seperti apa pom.xml saya. Saya juga menambahkan bagian properti di sana , di mana saya menunjukkan kepada Maven versi Java mana yang saya gunakan dalam kode sumber dan versi mana yang akan dikompilasi. Ini hanya agar saya tidak mendapat ide peringatan ketika memulai bahwa versi Java yang lama sedang digunakan. Anda bisa melakukannya, Anda tidak bisa) Di jendela kanan - Anda dapat melihat bahwa meskipun kami hanya menghubungkan konteks pegas - secara otomatis menambahkan inti, kacang, aop dan ekspresi. Dimungkinkan untuk menghubungkan setiap modul secara terpisah, mendaftarkan ketergantungan untuk masing-masing modul di memori dengan indikasi versi yang jelas, tetapi untuk saat ini kami senang dengan opsi seperti sekarang. Sekarang mari kita buat sebuah paket entities(entitas) dan buat 3 kelas di dalamnya: Cat, Dog, Parrot. Biarkan setiap hewan memiliki nama ( private String name, Anda dapat melakukan hardcode beberapa nilai di sana), dan pengambil/penyetel bersifat publik. Sekarang masuk ke kelas Maindan main()tulis sesuatu seperti ini di metode:
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());
}
Pertama, kita membuat objek konteks, dan di konstruktor kita memberinya nama paket yang perlu dipindai untuk mengetahui keberadaan kacang. Artinya, Spring akan memeriksa paket ini dan mencoba menemukan kelas yang ditandai dengan anotasi khusus yang membuat Spring tahu bahwa ini adalah kacang. Setelah itu ia membuat objek dari kelas-kelas ini dan menempatkannya dalam konteksnya. Setelah itu kita mendapatkan kucing dari konteks ini. Saat menangani objek konteks, kami memintanya untuk memberi kami kacang (objek), dan menunjukkan kelas objek apa yang kami butuhkan (di sini, omong-omong, Anda tidak hanya dapat menentukan kelas, tetapi juga antarmuka). Setelah itu Spring mengembalikan objek kelas ini kepada kita, yang kita simpan ke dalam variabel. Selanjutnya, kami meminta Spring untuk membelikan kami kacang yang disebut “anjing”. Ketika Spring membuat objek kelas, Dogia akan memberinya nama standar (jika nama kacang yang dibuat tidak ditentukan secara eksplisit), yaitu nama kelas objek tersebut, hanya dengan huruf kecil. Oleh karena itu, karena kelas kita dipanggil Dog, nama kacang tersebut adalah “anjing”. Jika kita memiliki objek di sana BufferedReader, maka Spring akan memberinya nama default “bufferedReader”. Dan karena dalam kasus ini (di Java) tidak ada kepastian pasti tentang kelas apa objek tersebut nantinya, maka hanya objek tertentu yang dikembalikan Object, yang kemudian kita masukkan secara manual ke tipe yang kita butuhkan Dog. Opsi dengan indikasi kelas yang jelas lebih nyaman. Nah, dalam kasus ketiga, kita mendapatkan kacang berdasarkan kelas dan nama. Mungkin ada situasi ketika dalam konteksnya akan ada beberapa kacang dari kelas yang sama, dan untuk menunjukkan kacang mana yang kita butuhkan, kami menunjukkan namanya. Karena kami juga dengan jelas menunjukkan kelasnya di sini, kami tidak perlu lagi melakukan cast. Penting!Jika ternyata Spring menemukan beberapa kacang sesuai dengan persyaratan yang kami tentukan, Spring tidak akan dapat menentukan kacang mana yang akan diberikan kepada kami dan akan mengeluarkan pengecualian. Oleh karena itu, cobalah untuk menunjukkan kepadanya setepat mungkin tempat sampah mana yang Anda butuhkan, agar situasi seperti itu tidak muncul. Jika Spring tidak menemukan satu kacang pun dalam konteksnya sesuai dengan kondisi Anda, Spring juga akan mengeluarkan pengecualian. Baiklah, kita cukup menampilkan nama-nama hewan kita di layar untuk memastikan bahwa ini benar-benar objek yang kita butuhkan. Namun jika kita menjalankan programnya sekarang, kita akan melihat bahwa Spring bersumpah tidak dapat menemukan hewan yang kita perlukan dalam konteksnya. Hal ini terjadi karena dia tidak menciptakan kacang tersebut. Seperti yang sudah saya katakan, ketika Spring memindai kelas, ia mencari anotasi Spring “nya” di sana. Dan jika ia tidak menemukannya, maka ia tidak menganggap kelas-kelas seperti itu sebagai kelas-kelas yang perlu ia ciptakan. Untuk memperbaikinya, cukup tambahkan anotasi @Componentdi depan kelas di kelas hewan kita.
@Component
public class Cat {
	private String name = "Barsik";
	...
}
Tapi bukan itu saja. Jika kita perlu secara eksplisit menunjukkan kepada Spring bahwa kacang untuk kelas ini harus memiliki nama tertentu, nama ini dapat ditunjukkan dalam tanda kurung setelah anotasi. Misalnya, agar Spring memberi nama yang kita perlukan pada parrot-keshakacang nuri, yang mainnantinya akan kita terima nuri ini, kita perlu melakukan sesuatu seperti ini:
@Component("parrot-kesha")
public class Parrot {
	private String name = "Kesha";
	...
}
Inilah inti dari konfigurasi otomatis . Anda menulis kelas Anda, menandainya dengan anotasi yang diperlukan, dan menunjukkan ke Spring sebuah paket dengan kelas Anda, yang dilaluinya, mencari anotasi dan membuat objek dari kelas tersebut. Omong-omong, Spring tidak hanya akan mencari anotasi @Component, tetapi juga semua anotasi lain yang diwarisi dari anotasi ini. Misalnya, @Controller, @RestController, @Service, @Repositorydan lain-lain yang akan kita temui di artikel selanjutnya. Sekarang mari kita coba melakukan hal yang sama, tetapi menggunakan konfigurasi java . Pertama, mari kita hapus anotasi @Componentdari kelas kita. Untuk memperumit tugas, mari kita bayangkan bahwa ini bukan kelas yang kita tulis sendiri, yang dapat dengan mudah kita modifikasi, tambahkan sesuatu, termasuk anotasi. Seolah-olah kelas-kelas ini disimpan di suatu perpustakaan. Dalam hal ini, kami tidak dapat mengedit kelas-kelas ini dengan cara apa pun sehingga dapat diterima pada musim semi. Tapi kita membutuhkan objek dari kelas ini! Di sini kita memerlukan konfigurasi Java untuk membuat objek tersebut. Untuk memulainya, mari kita buat sebuah paket, misalnya configs, dan di dalamnya - kelas Java biasa, misalnya, MyConfigdan tandai dengan anotasi@Configuration
@Configuration
public class MyConfig {
}
Sekarang kita perlu sedikit mengubah main()cara kita membuat konteks dalam metode ini. Kita bisa langsung menentukan kelas kita dengan konfigurasi di sana:
ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class);
Jika kita memiliki beberapa kelas berbeda tempat kita membuat kacang dan kita ingin menghubungkan beberapa kelas sekaligus, kita cukup menunjukkannya di sana, dipisahkan dengan koma:
ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class, MyAnotherConfig.class);
Nah, jika kita punya terlalu banyak, dan kita ingin menghubungkan semuanya sekaligus, kita cukup tunjukkan di sini nama paket di mana kita memilikinya:
ApplicationContext context =
	new AnnotationConfigApplicationContext("ru.javarush.info.fatfaggy.animals.configs");
Dalam hal ini, Spring akan menelusuri paket ini dan menemukan semua kelas yang ditandai dengan anotasi @Configuration. Nah, jika kita mempunyai program yang sangat besar yang konfigurasinya dibagi menjadi beberapa paket berbeda, kita cukup menunjukkan nama paket dengan konfigurasi yang dipisahkan dengan koma:
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");
Nah, atau nama paket yang lebih umum untuk semuanya:
ApplicationContext context =
	new AnnotationConfigApplicationContext("ru.javarush.info.fatfaggy.animals");
Anda dapat melakukannya sesuai keinginan, tetapi menurut saya opsi pertama, di mana Anda cukup menentukan kelas dengan konfigurasi, akan paling sesuai dengan program kami. Saat membuat konteks, Spring akan mencari kelas-kelas yang ditandai dengan anotasi @Configurationdan membuat objek dari kelas-kelas ini sendiri. Setelah itu ia akan mencoba memanggil metode di kelas-kelas ini yang ditandai dengan anotasi @Bean, yang berarti bahwa metode tersebut akan mengembalikan kacang (objek) yang telah ditempatkan dalam konteksnya. Nah, sekarang mari kita buat kacang kucing, anjing, dan burung beo di kelas kita dengan konfigurasi java. Hal ini dilakukan cukup sederhana:
@Bean
public Cat getCat() {
	return new Cat();
}
Ternyata kami secara manual membuat kucing kami sendiri dan memberikannya kepada Spring, dan dia sudah menempatkan objek kami ini dalam konteksnya. Karena kita tidak secara eksplisit menentukan nama kacang kita, Spring akan memberikan nama kacang yang sama dengan nama metodenya. Dalam kasus kita, kacang kucing akan diberi nama " getCat". Namun karena di main-e kita masih mendapatkan kucing tersebut bukan berdasarkan namanya, melainkan berdasarkan kelasnya, maka dalam hal ini nama bin tersebut tidak penting bagi kita. Buatlah kacang dengan seekor anjing dengan cara yang sama, namun perlu diingat bahwa Spring akan menamai kacang tersebut dengan nama metodenya. Untuk secara eksplisit memberi nama kacang kita dengan burung beo, cukup sebutkan namanya dalam tanda kurung setelah anotasi @Bean:
@Bean("parrot-kesha")
public Object weNeedMoreParrots() {
	return new Parrot();
}
Seperti yang Anda lihat, di sini saya menunjukkan jenis nilai yang dikembalikan Object, dan memanggil metode apa pun. Ini tidak mempengaruhi nama kacang dengan cara apa pun karena kami menetapkannya secara eksplisit di sini. Namun lebih baik untuk menunjukkan jenis nilai kembalian dan nama metode tidak secara tiba-tiba, tetapi kurang lebih dengan jelas. Bahkan untuk diri Anda sendiri, ketika Anda membuka proyek ini dalam setahun. :) Sekarang mari kita pertimbangkan situasi di mana untuk membuat satu kacang kita perlu menggunakan kacang lain . Misalnya, kita ingin nama kucing di cat bean terdiri dari nama burung beo dan string "-killer". Tidak masalah!
@Bean
public Cat getCat(Parrot parrot) {
	Cat cat = new Cat();
	cat.setName(parrot.getName() + "-killer");
	return cat;
}
Di sini Spring akan melihat bahwa sebelum membuat kacang ini, dia perlu memindahkan kacang nuri yang sudah dibuat ke sini. Oleh karena itu, dia akan membangun rantai panggilan ke metode kita sehingga metode untuk membuat burung beo dipanggil terlebih dahulu, dan kemudian meneruskan burung beo tersebut ke metode untuk membuat kucing. Di sinilah hal yang disebut injeksi ketergantungan bekerja : Spring sendiri meneruskan kacang nuri yang diperlukan ke metode kami. Jika idenya mengeluh tentang variabel parrot, jangan lupa untuk mengubah tipe kembalian dalam metode membuat burung beo dari Objectmenjadi Parrot. Selain itu, konfigurasi Java memungkinkan Anda untuk mengeksekusi semua kode Java dalam metode pembuatan kacang. Anda benar-benar dapat melakukan apa saja: membuat objek tambahan lainnya, memanggil metode lain, bahkan yang tidak ditandai dengan anotasi pegas, membuat loop, kondisi - apa pun yang terlintas dalam pikiran Anda! Semua ini tidak dapat dicapai dengan menggunakan konfigurasi otomatis, apalagi menggunakan konfigurasi xml. Sekarang mari kita lihat masalah yang lebih menyenangkan. Dengan polimorfisme dan antarmuka :) Mari kita buat antarmuka WeekDaydan buat 7 kelas yang akan mengimplementasikan antarmuka ini: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday. Mari kita buat metode di antarmuka String getWeekDayName()yang akan mengembalikan nama hari dalam seminggu dari kelas yang bersangkutan. Artinya, kelas Mondayakan mengembalikan " monday", dll. Katakanlah tugas saat meluncurkan aplikasi kita adalah menempatkan kacang dalam konteks yang sesuai dengan hari saat ini dalam seminggu. Tidak semua kacang dari semua kelas yang mengimplementasikan WeekDayantarmuka, tetapi hanya yang kita butuhkan. Itu bisa dilakukan seperti ini:
@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();
	}
}
Di sini tipe nilai yang dikembalikan adalah antarmuka kita, dan metode mengembalikan objek nyata dari kelas implementasi antarmuka tergantung pada hari saat ini dalam seminggu. Sekarang dalam metode main()kita dapat melakukan ini:
WeekDay weekDay = context.getBean(WeekDay.class);
System.out.println("It's " + weekDay.getWeekDayName() + " today!");
Ia memberi tahu saya bahwa hari ini adalah hari Minggu :) Saya yakin jika saya menjalankan program besok, objek yang sama sekali berbeda akan muncul dalam konteksnya. Harap dicatat bahwa di sini kita mendapatkan kacang hanya dengan antarmuka: context.getBean(WeekDay.class). Spring akan melihat konteksnya untuk melihat kacang mana yang mengimplementasikan antarmuka seperti itu dan akan mengembalikannya. Nah, ternyata WeekDayada objek bertipe dalam variabel bertipe Sunday, dan polimorfisme yang sudah tidak asing lagi bagi kita semua dimulai saat bekerja dengan variabel tersebut. :) Dan beberapa kata tentang pendekatan gabungan , di mana beberapa kacang dibuat oleh Spring sendiri, menggunakan pemindaian paket untuk mengetahui keberadaan kelas dengan anotasi @Component, dan beberapa kacang lainnya dibuat menggunakan konfigurasi java. Untuk melakukan ini, mari kembali ke versi asli, ketika kelas Cat, Dogdan Parrotditandai dengan anotasi @Component. Katakanlah kita ingin membuat tempat sampah untuk hewan kita menggunakan pemindaian otomatis paket entitiespada musim semi, namun membuat tempat sampah dengan hari dalam seminggu seperti yang baru saja kita lakukan. Yang perlu Anda lakukan hanyalah menambahkan di level kelas MyConfig, yang kami tentukan saat membuat konteks di mainanotasi -th @ComponentScan, dan menunjukkan dalam tanda kurung paket yang perlu dipindai dan kacang dari kelas yang diperlukan dibuat secara otomatis:
@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();
		}
	}
}
Ternyata saat membuat konteks, Spring melihat bahwa ia perlu memproses kelas MyConfig. Dia masuk ke dalamnya dan melihat bahwa dia perlu memindai paket " ru.javarush.info.fatfaggy.animals.entities" dan membuat kacang dari kelas-kelas itu, setelah itu dia mengeksekusi metode getDay()dari kelas tersebut MyConfigdan menambahkan tipe kacang WeekDayke konteksnya. Dalam metode ini, main()kita sekarang memiliki akses ke semua kacang yang kita perlukan: baik objek hewan maupun kacang dengan hari dalam seminggu. Bagaimana memastikan bahwa Spring juga mengambil beberapa konfigurasi xml - cari sendiri di Internet jika perlu :) Ringkasan:
  • coba gunakan konfigurasi otomatis;
  • selama konfigurasi otomatis, kami menunjukkan nama paket yang berisi kelas-kelas yang kacangnya perlu dibuat;
  • kelas-kelas tersebut ditandai dengan anotasi@Component;
  • pegas melewati semua kelas tersebut dan menciptakan objeknya serta menempatkannya dalam konteks;
  • jika konfigurasi otomatis karena alasan tertentu tidak cocok untuk kami, kami menggunakan konfigurasi Java;
  • dalam hal ini, kita membuat kelas Java biasa yang metodenya akan mengembalikan objek yang kita perlukan, dan menandai kelas tersebut dengan anotasi @Configurationjika kita memindai seluruh paket daripada menentukan kelas tertentu dengan konfigurasi saat membuat konteks;
  • metode kelas ini yang mengembalikan kacang ditandai dengan anotasi @Bean;
  • jika kita ingin mengaktifkan pemindaian otomatis saat menggunakan konfigurasi java, kita menggunakan anotasi @ComponentScan.
Jika belum ada yang jelas, cobalah membaca artikel ini beberapa hari lagi. Nah, atau jika Anda berada di level awal Javarash, mungkin masih terlalu dini bagi Anda untuk mempelajari musim semi. Anda selalu dapat kembali ke artikel ini nanti, ketika Anda sudah merasa lebih percaya diri dalam pemrograman di Java. Jika semuanya sudah jelas, Anda dapat mencoba mentransfer beberapa proyek favorit Anda ke Spring :) Jika ada yang jelas, tetapi ada yang kurang, silakan beri komentar :) Ada juga saran dan komentar jika saya melangkah ke suatu tempat atau saya menulis sesuatu yang bodoh ) Pada artikel selanjutnya kita akan mendalami spring-web-mvc dan membuat aplikasi web sederhana menggunakan spring.
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION