網(wǎng)站首頁 編程語言 正文
導(dǎo)讀:? ? ? ?
? ?????????我們在剛開始進(jìn)行spring的學(xué)習(xí)時, 大部分都是在applicationContext.xm的配置文件中向IOC容器中注入bean,但是這種方式實(shí)在是有點(diǎn)麻煩,所以從spring的2.5版本開始就引入注解的方式來幫助我們簡化bean的配置,而現(xiàn)在spring版本已經(jīng)升級到5.0以上了,使用注解的方式來進(jìn)行配置bean已經(jīng)越來越普遍,在springboot中更是沒有了applicationContext.xml的配置文件,都是采用注解的方式來進(jìn)行IOC的注入,所以了解如何用注解來進(jìn)行bean的配置變得很重要了。
IOC相關(guān)的注解
@Configuration注解
? ? ? ? 作用:在applicationContext.xml配置文件中我們配置bean都是在<beans></beans>標(biāo)簽中進(jìn)行的,而在純注解的配置中我們不需要applicationContext.xml這個文件,所以在這里Configuration注解就相當(dāng)于applicationContext.xml中的beans標(biāo)簽
? ? ? ? 使用:? 在一個類前加上這個注解即可,該類就相當(dāng)于一個beans標(biāo)簽了
//該類就相當(dāng)于一個空的beans標(biāo)簽了
@Configuration
public class UserDao {
}
啟動容器
????????與通過配置文件啟動容器的方式相同,只不過是使用AnnotationConfigApplicationContext這個實(shí)現(xiàn)類傳入字節(jié)碼對象即可
public class Main {
public static void main(String[] args) {
//傳入@Configuration注解所在類的Class對象
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(UserDao.class);
}
}
@ComponentScan注解(包掃描注解)
????????作用: 我們在使用配置注解(比如@Autowired,@Component等注解,下面會講)時, 如果我們只是在一個方法或者類前寫一個注解,那么spring怎么知道我們要將哪個類交給IOC容器管理呢,所以這個注解的作用就是告訴spring要掃描哪些包下的類,將這些配置了注解的類交給IOC容器管理
? ? ? ? 使用:?在添加了@Configuration的注解類前加上此注解, 并且指定basePackages屬性的值即可.
@Configuration
//basePackages為一個字符串?dāng)?shù)組,指定要進(jìn)行掃描的包
@ComponentScan(basePackages = {包1, 包2, .....})
public class UserDao {
}
@Component注解
????????作用:將一個類注入IOC容器中,相當(dāng)于先前配置文件中的bean標(biāo)簽
? ? ? ? 使用:? 在一個類前加上此注解即可, 有一個value參數(shù),作用是指定注入類的名稱,相當(dāng)于bean標(biāo)簽中的id屬性.也可以省略不寫,默認(rèn)為類名首字母小寫名稱,例如Plant類的默認(rèn)名稱為plant
//將Animal類交給IOC容器管理
@Component(value = "animals")
public class Animal {
public Animal(){
System.out.println("Animal is creating....");
}
}
@Controller,@Service,@Repository注解
? ? ? ? 與上面的@Component注解作用與用法一樣,只是幫助我們標(biāo)識此類在項目中的層面罷了,
@Controller常用于控制層(其實(shí)在后面的web開發(fā)中,被它修飾的類中的方法默認(rèn)都是一個Servlet,現(xiàn)在了解即可),@Service用于業(yè)務(wù)層,@Repository用于數(shù)據(jù)操作層。
@Scope注解
? ? ? ? 作用:指定類的制造方式為單例還是單例
? ? ? ? 使用:放置在類前面即可,指定為單例還是多例模式
@Component(value = "animals")
@Scope("singleton")//或者prototype
public class Animal {
public Animal(){
System.out.println("Animal is creating....");
}
}
@PostConstruct,@PreDestroy注解
????????作用:為一個類指定初始化(@PostConstruct)或者銷毀(@PreDestroy)方法,相當(dāng)于bean標(biāo)簽中的init-method和destroy-method方法
? ? ? ? 使用:在一個想要充當(dāng)初始化或者銷毀方法的方法前添加此注解
@Component(value = "animals")
public class Animal {
public Animal(){
System.out.println("Animal is creating....");
}
//初始化方法
@PostConstruct
public void init(){
System.out.println("Animal is initializing...");
}
//銷毀方法
@PreDestroy
public void destroy(){
System.out.println("Animal is destroying");
}
}
測試:
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(UserDao.class);
Animal animal = applicationContext.getBean(Animal.class);
//在退出虛擬機(jī)之前銷毀IOC容器
applicationContext.registerShutdownHook();
}
}
結(jié)果:
Animal is creating....
Animal is initializing...
Animal is destroying
進(jìn)程已結(jié)束,退出代碼0
DI相關(guān)注解
?@Autowired,@Resource, @Qualifier(需配合Autowired注解使用)注解
? ? ? ? 作用: 這些注解都是用來自動裝配引用類型的注解,裝配的bean必須在IOC容器中存在
? ? ? ? 使用: 在一個setter或者字段名之前都可以添加使用.
//新建一個Person類,Person類有一個類型為Animal的字段animal
public class Person {
//添加到字段之前也是可以的
// @Autowired
private Animal animal;
public Person(){
System.out.println("Person is creating....");
}
//setter方法前也可以,自動裝配該字段
@Autowired
public void setAnimal(Animal animal) {
this.animal = animal;
}
}
? ? ? ? 區(qū)別:
@Autowired:
@Autowired注解是默認(rèn)首先按照類型裝配的(byType),如果找不到對應(yīng)類型的bean或者找到多個類型相同的bean,則再按照名稱進(jìn)行裝配(byName)。如果想直接指定名稱進(jìn)行裝配則需要配合@Qualifier注解進(jìn)行使用:
首先我們創(chuàng)建兩個類型一樣的bean,一個為animal,一個為animal1
?然后我們在字段animals前添加此注解,由于@Autowired先根據(jù)類型進(jìn)行裝配,但是IOC中有兩個類型相同的bean(animal和animal1),如前面所說,當(dāng)找到多個類型的bean時,@Autowired注解會按照名稱進(jìn)行裝配,所以這里就會按照bean的名稱進(jìn)行裝配,但是這里變量的名稱為animals,而兩個bean的名稱為animal和animal1(與變量名稱不同,因為是按名稱裝配所以裝配不成功),所以這里就會報錯
@Component
public class Person {
@Autowired
private Animal animals;
public Person(){
System.out.println("Person is creating....");
}
public void printAnimal(){
//打印自動裝配的animals
System.out.println("animal is" + animals);
}
}
開啟測試:
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(UserDao.class);
Person person = applicationContext.getBean(Person.class);
person.printAnimal();
}
}
結(jié)果:
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'person': Unsatisfied dependency expressed through field 'animal1s'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'cn_java_factory.Animal' available: expected single matching bean but found 2: animal,animal1
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'person': Unsatisfied dependency expressed through field 'animal1s'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'cn_java_factory.Animal' available: expected single matching bean but found 2: animal,animal1
但是我們只要將字段名改為"animal"或者"animal1"就會運(yùn)行成功
@Autowired
//animal1或者animal都可以
private Animal animal;
結(jié)果:
Person is creating....
animal iscn_java_factory.Animal@3b69e7d1
進(jìn)程已結(jié)束,退出代碼0
還可以直接為@Autowired注解指定以名稱進(jìn)行裝配,這時就要使用@Qualifier注解,例如:
@Autowired
@Qualifier("animal")
private Animal myAnimal;
我們這里使用@Qualifier注解指定@Autowired以指定名稱進(jìn)行裝配(@Qualifier必須配合@Autowired使用),所以@Autowired會找到名稱為"animal"的bean裝配給myAnimal這個屬性。
@Resource
? ? ? ? @Resource注解如果沒有指定name和type屬性則默認(rèn)以名稱進(jìn)行裝配,當(dāng)注解寫在字段上時,默認(rèn)取字段名為指定名稱,如果沒有找到對應(yīng)的bean,則再以類型進(jìn)行自動裝配,如果找不到或者找到多個同一類型的bean則報錯;如果指定name屬性則只會按照名稱進(jìn)行裝配,沒有找到指定的名稱則報錯,如果指定type屬性則只會按照類型進(jìn)行裝配,如果找不到或者找到多個同一類型的bean則報錯;
@Value注解
? ? ? ? 作用:給簡單類型字段進(jìn)行賦值
? ? ? ? 使用:在簡單類型字段前添加即可
@Component
public class Person {
//為String類型賦值
@Value("jack")
private String username;
@Value("20")
private int age;
public Person(){
System.out.println("Person is creating....");
}
public void print(){
System.out.println("username is " + username + ", age " + age);
}
}
測試:
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(UserDao.class);
Person person = applicationContext.getBean(Person.class);
person.print();
}
}
結(jié)果:
Person is creating....
username is jack, age 20
進(jìn)程已結(jié)束,退出代碼0
可以看出值已經(jīng)注入進(jìn)去了;
@Value還可以讀取properties配置文件中的值:
1.通過@PropertySource注解將properties文件加載進(jìn)來
@Configuration
@ComponentScan(basePackages = {"cn_java_factory"})
//info.properties為在resources文件夾下的配置文件,最好加上"classpath:"這個前綴
@PropertySource("classpath:info.properties")
public class UserDao {
}
2.通過${屬性名}進(jìn)行引用
@Component
public class Person {
//hobby為info.properties中的屬性名
@Value("${hobby}")
private String hobby;
@Value("${weight}")
private int weight;
@Value("${height}")
private double height;
public Person(){
System.out.println("Person is creating....");
}
public void print(){
System.out.println("weight " + weight + " height" + height + " hobby " + hobby);
}
}
@Bean注解
? ? ? ? 作用: 將靜態(tài)工廠方法或者實(shí)例工廠方法的返回對象注入到IOC容器中
? ? ? ? 使用: 在工廠方法前加上此注解即可,可通過value指定bean的名稱,如果不進(jìn)行指定的話默認(rèn)為方法名名稱。
@Configuration
@ComponentScan(basePackages = {"cn_java_factory"})
@PropertySource("classpath:info.properties")
public class UserDao {
//靜態(tài)工廠
@Bean("animals")
public static Animal getAnimal(){
return new Animal();
}
//實(shí)例工廠
@Bean
public Person getPerson(){
return new Person();
}
}
從下圖可以看出@Bean如果沒有指定value值則會使用方法名作為bean的名稱,并且已經(jīng)成功的將工廠方法產(chǎn)生的對象注入到IOC容器中了
?@Import注解
? ? ? ? 當(dāng)我們在被@Configuratin注解修飾的類中寫多個被@Bean修飾的工廠方法時,可能會使修飾的類變得臃腫龐大,所以我們可以通過@Import注解將其它類中的被@Bean修飾的方法名引入進(jìn)來來.
@Configuration
@ComponentScan(basePackages = {"cn_java_factory"})
@PropertySource("classpath:info.properties")
//引入其它類中的被@Bean修飾的工廠方法
@Import(PersonFactory.class)
public class UserDao {
}
PersonFactory類:
public class PersonFactory{
//靜態(tài)工廠
@Bean("animals")
public static Animal getAnimal(){
return new Animal();
}
//實(shí)例工廠
@Bean
public Person getPerson(){
return new Person();
}
}
結(jié)果:
?可以看出工廠方法返回的對象也被注入到IOC中了
上面這些注解就是我們在spring配置中常用的注解了,感謝您的閱讀!!
原文鏈接:https://blog.csdn.net/qq_62698326/article/details/127577152
相關(guān)推薦
- 2022-02-19 AttributeError: ‘str‘ object has no attribute ‘dec
- 2022-08-12 利用Python判斷文件的幾種方法及其優(yōu)劣對比_python
- 2022-09-04 python接口自動化之正則用例參數(shù)化的示例詳解_python
- 2022-06-28 一文搞懂Python中的進(jìn)程,線程和協(xié)程_python
- 2023-05-15 GoLang中的加密方法小結(jié)_Golang
- 2022-03-26 Qt?多語言程序設(shè)計的實(shí)現(xiàn)_C 語言
- 2022-10-14 初識RPC中間件zeroC ICE工具之iceca
- 2022-12-13 bat文件與Vbs文件之間的常用操作(獲取用戶輸入,執(zhí)行VBS文件)_DOS/BAT
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支