CodeGym /Blog Java /rawak /Spring untuk orang malas Asas, konsep asas dan contoh den...
John Squirrels
Tahap
San Francisco

Spring untuk orang malas Asas, konsep asas dan contoh dengan kod. Bahagian 2

Diterbitkan dalam kumpulan
Dalam artikel sebelum ini , saya menerangkan secara ringkas apa itu Spring dan apa itu kacang dan konteks. Kini tiba masanya untuk mencubanya. Saya akan melakukannya menggunakan IntelliJ IDEA Enterprise Edition. Tetapi semua contoh saya juga harus berfungsi dalam Edisi Komuniti IntelliJ IDEA percuma. Dalam tangkapan skrin, jika anda melihat bahawa saya mempunyai beberapa tetingkap yang anda tidak miliki, jangan risau — ia tidak penting untuk projek ini :) Spring untuk orang malas Asas, konsep asas dan contoh dengan kod.  Bahagian 2 - 1Mula-mula, buat projek Maven kosong. Saya menunjukkan cara melakukan ini dalam artikel di pautan ini . Baca sehingga perkataan " Tiba masanya untuk kami menukar projek Maven kami kepada projek web. " — selepas itu, artikel itu menunjukkan cara membuat projek web, tetapi kami tidak memerlukannya sekarang. Dalam src/main/javafolder, buat pakej (dalam kes saya, saya memanggilnya " en.codegym.info.fatfaggy.animals. Anda boleh memanggilnya apa sahaja yang anda mahu. Cuma jangan lupa untuk menggantikan nama pakej saya dengan nama pakej anda di semua tempat yang betul. Sekarang buat kelas dan Maintambahkan kaedah

public static void main(String[] args) {
    ...
}
Selepas itu, buka fail pom.xml dan tambah dependenciesbahagian itu. Sekarang pergi ke repositori Maven dan cari konteks Spring untuk versi stabil terkini. Letakkan apa yang kita temui ke dalam dependenciesbahagian. Saya menerangkan proses ini dengan lebih terperinci dalam artikel CodeGym yang lain ini (lihat bahagian bertajuk " Menyambung kebergantungan dalam Maven "). Kemudian Maven sendiri akan mencari dan memuat turun kebergantungan yang diperlukan. Pada akhirnya, anda sepatutnya mendapat sesuatu seperti ini: Spring untuk orang malas Asas, konsep asas dan contoh dengan kod.  Bahagian 2 - 2Dalam tetingkap di sebelah kiri, anda boleh melihat struktur projek dengan pakej dan kelas Main. Tetingkap tengah menunjukkan cara pom.xml melihat saya. Saya juga menambah sifatbahagian kepadanya. Bahagian ini memberitahu Maven versi Java yang saya gunakan dalam fail sumber saya dan versi yang hendak disusun. Ini hanya supaya IDEA tidak memberi amaran kepada saya bahawa saya menggunakan versi lama Java. Ini adalah pilihan :) Tetingkap kanan menjelaskan bahawa walaupun kami hanya menyambungkan modul konteks musim bunga, ia secara automatik menarik modul teras spring, kacang musim bunga, spring-aop dan ekspresi musim bunga. Kami boleh menyambung setiap modul secara berasingan, menulis kebergantungan untuk setiap modul dengan versi eksplisit dalam fail pom.xml, tetapi buat masa ini kami berpuas hati dengan perkara yang ada. Sekarang buat entitiespakej dan buat 3 kelas di dalamnya: Cat, Dog, Parrot. Mari kita beri nama setiap haiwan (private String name— anda boleh hardcode beberapa nilai di sana). Pengambil/penetap adalah awam. Sekarang kita beralih ke Mainkelas dan main()kaedah, dan kita menulis sesuatu seperti ini:

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());
}
Mula-mula, kami mencipta objek konteks, memberitahu pembina pakej mana yang perlu dicari untuk mencari kacang. Dalam erti kata lain, Spring akan melalui pakej ini dan cuba mencari kelas yang ditandakan dengan anotasi khas yang menunjukkan ia adalah kacang. Kemudian ia mencipta objek kelas ini dan meletakkannya dalam konteks. Selepas itu, kami mendapat kucing dari konteks ini. Kami memanggil objek konteks untuk memberi kami kacang (objek), menunjukkan kelas objek yang kami mahu (dengan cara ini, kami juga boleh menentukan antara muka, bukan hanya kelas). Selepas itu, Spring mengembalikan objek kelas yang diminta, yang kemudian kami simpan dalam pembolehubah. Seterusnya, kami meminta Spring untuk mendapatkan kami kacang yang dipanggil "anjing". Apabila Spring mencipta aDogobjek, ia memberikan objek nama standard (melainkan kacang yang dicipta telah diberi nama secara eksplisit), iaitu nama kelas tetapi dengan huruf kecil awal. Dalam kes ini, kelas kami dipanggil Dog, jadi nama kacang itu ialah "anjing". Jika kita memerlukan BufferedReaderobjek di sana , maka Spring akan menamakannya "bufferedReader". Dan kerana Java tidak boleh 100% pasti kelas mana yang kita mahu, ia mengembalikan objek Object, yang kemudiannya kita hantar secara manual ke jenis yang dikehendaki, iaituDog. Pilihan di mana kelas ditunjukkan secara eksplisit adalah lebih mudah. Pilihan ketiga ialah mendapatkan kacang mengikut nama kelas dan dengan nama kacang. Ada kemungkinan bahawa konteks mungkin mempunyai beberapa biji kelas tunggal. Untuk menunjukkan kacang tertentu yang kami perlukan, kami menunjukkan namanya. Oleh kerana kami juga menunjukkan kelas secara eksplisit di sini, kami tidak perlu lagi melakukan lakonan. PENTING!Jika Spring menemui beberapa kacang yang sepadan dengan keperluan kami, maka ia tidak dapat menentukan kacang yang akan diberikan kepada kami, jadi ia akan membuang pengecualian. Sehubungan itu, untuk mengelakkan situasi ini, anda harus cuba sespesifik mungkin dalam memberitahu Spring kacang yang anda perlukan. Jika Spring mencari konteksnya dan gagal menemui sebiji kacang yang sepadan dengan keperluan kami, maka ia juga akan mengeluarkan pengecualian. Akhir sekali, kami hanya memaparkan nama haiwan kami untuk mengesahkan bahawa kami benar-benar mendapat objek yang kami perlukan. Tetapi jika kita menjalankan program sekarang, kita akan melihat bahawa Spring tidak berpuas hati — ia tidak dapat mencari haiwan yang kita perlukan dalam konteksnya. Ini kerana ia tidak mencipta kacang ini. Seperti yang saya katakan sebelum ini, apabila Spring mengimbas kelas, ia mencari anotasi Springnya sendiri. Dan jika Spring tidak menemui anotasi ini, maka ia tidak t berpendapat bahawa kelas ini sepadan dengan kacang yang perlu dibuatnya. Memperbaiki ini hanya memerlukan penambahan@Componentanotasi di hadapan setiap kelas haiwan kami.

@Component
public class Cat {
	private String name = "Oscar";
	...
}
Tetapi ada lagi. Jika kami perlu memberitahu Spring dengan jelas bahawa kacang untuk kelas ini harus mempunyai nama tertentu, kami menunjukkan nama dalam kurungan selepas anotasi. Sebagai contoh, untuk memberitahu Spring memberi nama " parrot-polly" kepada kacang nuri, iaitu nama yang akan kita gunakan untuk mendapatkan nuri ini dalam mainkaedah, kita harus melakukan sesuatu seperti ini:

@Component("parrot-polly")
public class Parrot {
	private String name = "Polly";
	...
}
Ini adalah titik keseluruhan konfigurasi automatik . Anda menulis kelas anda, tandakannya dengan anotasi yang diperlukan dan beritahu Spring pakej yang mempunyai kelas anda. Ini ialah pakej yang akan dijalankan oleh rangka kerja untuk mencari anotasi dan mencipta objek bagi kelas ini. Ngomong-ngomong, Spring bukan sahaja mencari @Componentanotasi, tetapi juga semua anotasi lain yang mewarisi anotasi ini. Contohnya, @Controller, @RestController, @Service, @Repository, dan banyak lagi, yang akan kami perkenalkan dalam artikel akan datang. Sekarang kita akan cuba melakukan perkara yang sama menggunakan konfigurasi berasaskan Java . Untuk bermula, alih keluar@Componentanotasi daripada kelas kami. Untuk menjadikan perkara lebih mencabar, bayangkan bahawa kami tidak menulis kelas ini, jadi kami tidak boleh mengubah suainya dengan mudah, yang bermaksud kami tidak boleh menambah anotasi. Ia seperti kelas ini dibungkus dalam beberapa perpustakaan. Dalam kes ini, tiada cara untuk kami mengedit kelas ini supaya ia dikenali oleh Spring. Tetapi kita memerlukan objek kelas ini! Di sini kita memerlukan konfigurasi berasaskan Java untuk mencipta objek. Untuk bermula, buat pakej dengan nama seperti configs. Dalam pakej ini, buat kelas Java biasa, seperti MyConfig, dan tandai dengan @Configurationanotasi.

@Configuration
public class MyConfig {
}
Sekarang kita perlu mengubah main()kaedah, mengubah cara kita mencipta konteks. Kita boleh sama ada secara eksplisit menunjukkan kelas mana yang mempunyai konfigurasi kita:

ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class);
Jika kami mempunyai beberapa kelas berbeza yang mencipta kacang dan kami ingin menyambung beberapa daripadanya secara serentak, kami hanya menunjukkan semuanya di sana, dipisahkan dengan koma:

ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class, MyAnotherConfig.class);
Dan jika kami mempunyai terlalu banyak daripada mereka dan kami ingin menyambungkannya semua secara serentak, maka kami hanya menunjukkan nama pakej yang terkandung dalam:

ApplicationContext context =
	new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.configs");
Dalam kes ini, Spring akan melalui pakej dan mencari semua kelas yang ditandakan dengan @Configurationanotasi. Nah, dan jika kami mempunyai program yang sangat besar di mana konfigurasi dibahagikan kepada pakej yang berbeza, maka kami hanya menunjukkan senarai nama pakej yang dipisahkan koma yang mengandungi konfigurasi:

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");
Atau nama pakej yang biasa untuk mereka semua:

ApplicationContext context =
	new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals");
Anda boleh melakukannya walau bagaimanapun anda mahu, tetapi nampaknya pilihan pertama, yang hanya menunjukkan kelas dengan konfigurasi, paling sesuai dengan program kami. Apabila mencipta konteks, Spring mencari kelas yang ditandakan dengan @Configurationanotasi dan akan mencipta objeknya sendiri bagi kelas ini. Ia cuba memanggil kaedah yang ditandakan dengan @Beananotasi, yang bermaksud kaedah ini mengembalikan kacang (objek) yang Spring akan tambah pada konteks. Dan sekarang kami akan mencipta kacang untuk kucing, anjing dan burung kakak tua dalam kelas kami dengan konfigurasi berasaskan Java. Ini agak mudah dilakukan:

@Bean
public Cat getCat() {
	return new Cat();
}
Di sini kami mencipta kucing kami secara manual dan menyerahkannya kepada Spring, yang kemudiannya memegang objek kami dalam konteksnya. Oleh kerana kami tidak memberikan nama secara eksplisit kepada kacang kami, Spring akan memberikan nama yang sama dengan nama kaedah tersebut. Dalam kes kami, kacang kucing akan dipanggil " getCat". Tetapi kerana kami menggunakan kelas, bukan nama, untuk mendapatkan kacang kucing dalam mainkaedah, nama kacang itu tidak penting bagi kami. Begitu juga, cipta kacang anjing, dengan mengingati bahawa Spring akan memberikan nama kaedah kepada kacang itu. Untuk menamakan kacang nuri kami secara eksplisit, kami hanya menunjukkan namanya dalam kurungan selepas @Beananotasi:

@Bean("parrot-polly")
public Object weNeedMoreParrots() {
	return new Parrot();
}
Seperti yang anda lihat, di sini saya menunjukkan Objectjenis pulangan dan memberikan kaedah nama sewenang-wenangnya. Ini tidak menjejaskan nama kacang, kerana kami secara eksplisit menyatakan nama di sini. Namun, adalah lebih baik untuk menunjukkan nilai pulangan yang lebih kurang bermakna dan nama kaedah. Lakukan ini jika tidak ada sebab lain selain untuk membantu diri sendiri apabila anda membuka semula projek dalam setahun. :) Sekarang pertimbangkan keadaan di mana kita memerlukan satu biji untuk mencipta satu lagi kacang . Sebagai contoh, katakan kita mahu nama kucing dalam kacang kucing menjadi nama burung nuri ditambah tali "-killer". Tiada masalah!

@Bean
public Cat getCat(Parrot parrot) {
	Cat cat = new Cat();
	cat.setName(parrot.getName() + "-killer");
	return cat;
}
Di sini Spring akan melihat bahawa untuk mencipta kacang ini, rangka kerja perlu lulus dalam kacang nuri yang dibuat sebelum ini. Sehubungan itu, ia akan mengatur rantaian panggilan kaedah yang diperlukan: pertama, kaedah mencipta burung nuri dipanggil dan kemudian rangka kerja menghantar burung nuri baru kepada kaedah mencipta kucing. Di sinilah suntikan kebergantungan memainkan peranan: Spring sendiri menyerahkan kacang nuri yang diperlukan kepada kaedah kami. Jika IDEA kecewa dengan parrotpembolehubah, jangan lupa untuk menukar jenis pulangan kaedah penciptaan burung nuri daripada Objectkepada Parrot. Selain itu, konfigurasi berasaskan Java membolehkan anda menjalankan sebarang kod Java sepenuhnyadalam kaedah membuat kacang anda. Anda benar-benar boleh melakukan apa sahaja: mencipta objek tambahan lain, memanggil sebarang kaedah lain, walaupun yang tidak ditanda dengan anotasi Spring, mencipta gelung, syarat Boolean — apa sahaja yang terlintas di fikiran! Ini tidak semua boleh dilakukan dengan konfigurasi automatik, dan lebih kurang lagi dengan konfigurasi XML. Sekarang mari kita pertimbangkan masalah yang lebih menyeronokkan. Polimorfisme dan antara muka :) Kami akan mencipta WeekDayantara muka dan mencipta 7 kelas yang melaksanakan antara muka ini: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday. Kami akan memberikan antara muka String getWeekDayName()kaedah, yang akan mengembalikan nama hari dalam seminggu untuk kelas yang sepadan. Dengan kata lain, Mondaykelas akan kembali "Monday", dsb. Apabila memulakan aplikasi, katakan tugas kita adalah untuk meletakkan kacang yang sepadan dengan hari semasa dalam seminggu ke dalam konteks. Bukan kacang untuk semua kelas yang melaksanakan antara muka — hanya satu kacang yang kami perlukan. Anda WeekDayboleh lakukan itu kira-kira 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 jenis pulangan ialah antara muka kami. Kaedah ini mengembalikan objek bona fide salah satu kelas yang melaksanakan antara muka, bergantung pada hari semasa dalam minggu. Sekarang kita boleh melakukan perkara berikut dalam main()kaedah:

WeekDay weekDay = context.getBean(WeekDay.class);
System.out.println("Today is " + weekDay.getWeekDayName() + "!");
Bagi saya, program memberitahu saya hari Ahad :) Saya yakin jika saya menjalankan program esok, konteksnya akan mengandungi objek yang sama sekali berbeza. Ambil perhatian bahawa kami mendapat kacang hanya menggunakan antara muka: context.getBean(WeekDay.class). Spring akan mencari konteksnya untuk kacang yang melaksanakan antara muka, dan akan mengembalikannya. Kemudian ternyata WeekDaypembolehubah kami berakhir dengan objek Ahad, dan konsep polimorfisme yang biasa digunakan semasa kami bekerja dengan pembolehubah ini. :) Sekarang beberapa perkataan tentang pendekatan gabungan , di mana beberapa kacang dicipta secara automatik oleh Spring, sesetengahnya dengan mengimbas pakej untuk kelas dengan anotasi @Component, dan yang lain dengan konfigurasi berasaskan Java. Semasa kami mempertimbangkan perkara ini, kami akan kembali kepada versi asal, di mana Cat, Dog, danParrotkelas telah ditandakan dengan @Componentanotasi. Katakan kita ingin mencipta kacang untuk haiwan kita dengan meminta Spring mengimbas pakej secara automatik , entitiestetapi kita juga mahu mencipta kacang dengan hari dalam seminggu, seperti yang baru sahaja kita lakukan. Apa yang anda perlu lakukan ialah menambah @ComponentScananotasi pada tahap kelas MyConfig, yang kami nyatakan semasa mencipta konteks dalam main(), dan menunjukkan dalam kurungan pakej yang perlu diimbas dan mencipta kacang bagi kelas yang diperlukan secara automatik:

@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();
		}
	}
}
Apabila mencipta konteks, Spring melihat bahawa ia perlu memproses MyConfigkelas. Ia memasuki kelas dan melihat bahawa ia perlu mengimbas en.codegym.info.fatfaggy.animals.entitiespakej " " dan mencipta kacang bagi kelas tersebut, selepas itu ia melaksanakan kaedah MyConfigkelas getDay()dan menambah WeekDaykacang pada konteks. Dalam main()kaedah ini, kami kini mempunyai akses kepada semua kacang yang kami perlukan: kedua-dua objek haiwan dan kacang dengan hari dalam seminggu. Jika anda perlu membuat Spring juga mengambil beberapa fail konfigurasi XML, anda boleh melakukan carian web anda sendiri untuk mendapatkan penjelasan :) Ringkasan:
  • Cuba gunakan konfigurasi automatik
  • Semasa konfigurasi automatik, nyatakan nama pakej yang mengandungi kelas yang kacangnya perlu dibuat
  • Kelas ini ditandakan dengan @Componentanotasi
  • Spring berjalan melalui semua kelas ini, mencipta objek, dan meletakkannya dalam konteks;
  • Jika konfigurasi automatik tidak sesuai dengan kami atas sebab tertentu, kami menggunakan konfigurasi berasaskan Java
  • Dalam kes ini, kami mencipta kelas Java biasa yang kaedahnya mengembalikan objek yang kami perlukan. Kami menandakan kelas ini dengan @Configurationanotasi jika kami akan mengimbas keseluruhan pakej dan bukannya menunjukkan kelas tertentu dengan konfigurasi semasa mencipta konteks
  • Kaedah kelas ini yang mengembalikan kacang ditandakan dengan @Beananotasi
  • Jika kami ingin mendayakan pengimbasan automatik apabila menggunakan konfigurasi berasaskan Java, kami menggunakan anotasi @ComponentScan.
Jika artikel ini telah mengelirukan, cuba baca dalam beberapa hari. Atau jika anda berada di salah satu peringkat awal CodeGym, mungkin agak awal untuk anda belajar Spring. Anda sentiasa boleh kembali ke artikel ini sedikit kemudian apabila anda berasa lebih yakin dengan kemahiran pengaturcaraan Java anda. Jika semuanya jelas, maka anda boleh cuba menukar beberapa projek haiwan kesayangan anda kepada Spring :) Jika beberapa perkara jelas tetapi perkara lain tidak, sila tinggalkan komen :) Beritahu saya cadangan dan kritikan anda, jika saya tersilap di suatu tempat atau menulis sesuatu yang tidak masuk akal :) Dalam artikel seterusnya, kami akan menyelam secara tiba-tiba ke spring-web-mvc dan membuat aplikasi web mudah menggunakan Spring.
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION