1. 概述
在 Spring Boot常用注解(一) - 聲明Bean的注解 中學習了Spring Boot中聲明Bean的注解
那Spring容器中的Bean是怎么實現(xiàn)自動裝配(依賴)的呢骤素?
這就是接下來學習的注入注解咯
注入Bean的注解:
- @Autowired
- @Inject
- @Resource
2. @Autowired注解
@Autowired注解源碼:
package org.springframework.beans.factory.annotation;
/**
1. @since 2.5
2. @see AutowiredAnnotationBeanPostProcessor
3. @see Qualifier
4. @see Value
*/
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
- @Autowired注解作用在構造函數(shù)棚品、方法捧搞、方法參數(shù)置鼻、類字段以及注解上
- @Autowired注解可以實現(xiàn)Bean的自動注入
2.1 @Autowired注解原理
在Spring Boot應用啟動時不恭,Spring容器會自動裝載一個org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor處理器,當容器掃掃描到@Autowired注解時啦扬,就會在IoC容器就會找相應類型的Bean内狗,并且實現(xiàn)注入。
2.2 @Autowired注解使用
在Web MVC中控制層(Controller)訪問的是業(yè)務層(Service)唤蔗,而業(yè)務層(Service)訪問的是數(shù)據(jù)層(Dao),使用@Autowired注解實現(xiàn)注入
數(shù)據(jù)層:
package com.example.demo.chapter1.useannotation.autowired.dao;
/**
* 數(shù)據(jù)層接口探遵,用于訪問數(shù)據(jù)庫窟赏,返回數(shù)據(jù)給業(yè)務層
* */
public interface IDao {
public String get();
}
/**
* 數(shù)據(jù)層接口實現(xiàn)類
*
* 1.數(shù)據(jù)層Bean用@Repository標注
* 2.當前Bean的名稱是"autowiredUserDaoImpl"
* 3.設置當前Bean的為原型模式,即每次獲取Bean時都創(chuàng)建一個新實例
* */
@Repository("autowiredUserDaoImpl")
@Scope("prototype")
public class UserDaoImpl implements IDao {
public String get() {
return "@Autowired注解實現(xiàn)自動裝配";
}
}
業(yè)務層:
package com.example.demo.chapter1.useannotation.autowired.service;
/**
* 業(yè)務層接口
* 從數(shù)據(jù)層獲取數(shù)據(jù)箱季,處理結果返回給控制層
* */
public interface IService {
public String get();
}
/**
* 業(yè)務層接口實現(xiàn)
*
* 1.數(shù)據(jù)層Bean用@Service標注
* 2.當前Bean的名稱是"autowiredUserServiceImpl"
* 3.設置當前Bean的為原型模式涯穷,即每次獲取Bean時都創(chuàng)建一個新實例
* 4.業(yè)務層有一個數(shù)據(jù)層接口IDao,使用@Autowired注解標注
* */
@Service("autowiredUserServiceImpl")
@Scope("prototype")
public class UserServiceImpl implements IService {
/**
* @Autowired實現(xiàn)自動裝配
* Spring IoC容器掃描到@Autowired注解會去查詢IDao的實現(xiàn)類藏雏,并自動注入
* */
@Autowired
private IDao dao;
@Override
public String get() {
return dao.get();
}
}
- Bean通過注解@Service聲明為一個Spring容器管理的Bean拷况,Spring容器會掃描classpath路徑下的所有類,找到帶有@Service注解的UserServiceImpl類掘殴,并根據(jù)Spring注解對其進行初始化和增強赚瘦,命名為autowiredUserServiceImpl
- Spring容器如果發(fā)現(xiàn)此類屬性dao也有注解@Autowired,則會從Spring容器中查找一個已經(jīng)初始化好的IDao的實現(xiàn)類奏寨,如果沒有找到起意,則先初始化一個IDao實現(xiàn)類
控制層:
package com.example.demo.chapter1.useannotation.autowired.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.chapter1.useannotation.autowired.service.IService;
/**
1. 控制層
2.
3. 1.控制層使用@RestController注解標注,返回json格式的字符串
4. 2.獲取業(yè)務層返回的數(shù)據(jù)病瞳,輸出到客戶端
5. 3.請求:http:localhost:8080/autowiredController
6. */
@RestController
public class AutowiredController {
@Autowired
private IService service;
@RequestMapping("/autowiredController")
public String get () {
return service.get();
}
}
測試結果:
- 啟動Spring Boot應用
- 瀏覽器輸入:http:localhost:8080/autowiredController
-
返回結果:
2.3 @Qualifier注解
@Qualifier注解源碼:
package org.springframework.beans.factory.annotation;
/**
* @since 2.5
* @see Autowired
*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
String value() default "";
}
- 如果Spring 容器中有兩個數(shù)據(jù)層接口IDao的實現(xiàn)類
- 而業(yè)務層通過@Autowired注解標注的是IDao接口
- 這時就需要@Qualifier注解來指定需要自動裝配的Bean的名稱
- 否則會報如下的錯:
Description:
Field dao in com.example.demo.chapter1.useannotation.autowired.service.UserServiceImpl required a single bean, but 2 were found:
- autowiredAdminDaoImpl: defined in file [D:\eclipse\workspace\boot\demo\target\classes\com\example\demo\chapter1\useannotation\autowired\dao\AdminDaoImpl.class]
- autowiredUserDaoImpl: defined in file [D:\eclipse\workspace\boot\demo\target\classes\com\example\demo\chapter1\useannotation\autowired\dao\UserDaoImpl.class]
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
2.4 @Qualifier注解使用
數(shù)據(jù)層接口IDao:
public interface IDao {
public String get();
}
IDao實現(xiàn)類 - UserDaoImpl
@Repository("autowiredUserDaoImpl")
@Scope("prototype")
public class UserDaoImpl implements IDao {
public String get() {
return "@Autowired注解實現(xiàn)自動裝配 - UserDaoImpl";
}
}
IDao實現(xiàn)類 - AdminDaoImpl
@Repository("autowiredAdminDaoImpl")
@Scope("prorotype")
public class AdminDaoImpl implements IDao {
@Override
public String get() {
return "@Autowired注解實現(xiàn)自動裝配 - AdminDaoImpl";
}
}
@Qualifier注解使用:
@Service("autowiredUserServiceImpl")
@Scope("prototype")
public class UserServiceImpl implements IService {
/**
* @Autowired實現(xiàn)自動裝配
* Spring IoC容器掃描到@Autowired注解會去查詢IDao的實現(xiàn)類揽咕,并自動注入
* */
@Autowired
@Qualifier("autowiredUserDaoImpl")
private IDao dao;
@Override
public String get() {
return dao.get();
}
}
測試結果:
2.5 @Autowired注解的requird屬性
在使用@Autowired注解時,首先在容器中查詢對應類型的bean
- 如果查詢結果Bean剛好為一個套菜,自動注入
- 如果查詢結果Bean不止一個亲善,通過@Qualifier注解指定自動裝配Bean的名稱
- 如果沒有查詢到對應類型的Bean,由于默認@Autowired(required=true)笼踩,會拋出異常逗爹,解決方法是使用@Autoiwired(quired=false)
- @Autowired(quired=true)意味著依賴是必須的
- @Autowired(quired=false)等于告訴 Spring:在找不到匹配 Bean 時也不報錯
數(shù)據(jù)層接口:
package com.example.demo.chapter1.useannotation.autowired.dao;
/**
* 數(shù)據(jù)層接口
* */
public interface ITask {
public String get();
}
業(yè)務層接口:
package com.example.demo.chapter1.useannotation.autowired.service;
@Service("taskServiceImpl")
@Scope("prototype")
public class TaskServiceImpl implements IService {
@Autowired
private ITask task;
@Override
public String get() {
return task.get();
}
}
如果沒有接口ITask的實現(xiàn)類亡嫌,啟動Spring Boot應用會報如下錯:
沒有找到ITask的實現(xiàn)類
Description:
Field task in com.example.demo.chapter1.useannotation.autowired.service.TaskServiceImpl required a bean of type 'com.example.demo.chapter1.useannotation.autowired.dao.ITask' that could not be found.
Action:
Consider defining a bean of type 'com.example.demo.chapter1.useannotation.autowired.dao.ITask' in your configuration.
解決方法 - 添加required=false
@Service("autowiredTaskServiceImpl")
@Scope("prototype")
public class TaskServiceImpl implements IService {
/**
* 接口ITask沒有實現(xiàn)類
* 添加required=false不報錯
* */
@Autowired(required=false)
private ITask task;
@Override
public String get() {
return task.get();
}
}
>推薦一下我的公眾號: 【geekjc】嚎于,一起學習交流編程知識,分享經(jīng)驗挟冠,各種有趣的事于购,更多精彩內容,掃碼進入小程序知染。