掃描下方二維碼或者微信搜索公衆號
菜鳥飛呀飛
,便可關注微信公衆號,閱讀更多Spring源碼分析和Java併發編程文章。java
在平時工做中,只要是作Java開發,基本都離不開Spring框架,Spring的一大核心功能就是IOC,它能幫助咱們實現自動裝配,基本上天天咱們都會使用到@Autowired註解來爲咱們自動裝配屬性,那麼你知道Autowired註解的原理嗎?在閱讀本文以前,能夠先思考一下如下幾個問題。spring
先按照以下示例搭建一下本文的demo工程sql
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
複製代碼
@Configuration
@ComponentScan("com.tiantang.study")
public class AppConfig {
}
複製代碼
public interface UserService {
}
複製代碼
@Service
public class UserServiceImpl implements UserService {
}
複製代碼
public interface OrderService {
void query();
}
複製代碼
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private UserService userService;
public void query(){
System.out.println(userService);
}
}
複製代碼
public class MainApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
OrderService orderService = applicationContext.getBean(OrderService.class);
orderService.query();
}
}
複製代碼
經過上面的demo咱們完成了對OrderServiceImpl的自動裝配,爲其屬性userService完成了賦值操做,那麼Spring是如何經過@Autowired來實現賦值的呢?咱們知道,Spring在容器啓動階段,會先實例化bean,而後再對bean進行初始化操做。在初始化階段,會經過調用Bean後置處理來完成對屬性的賦值等操做,那麼同理,要想實現@Autowired的功能,確定也是經過後置處理器來完成的。這個後置處理器就是AutowiredAnnotationBeanPostProcessor。接下來咱們就來看看這個類的源碼。編程
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class)
啓動容器的時候,在構造方法中會調用到this()
方法,在this()
方法中最終會調用到registerAnnotationConfigProcessors()
方法,在該方法中,Spring會向容器註冊7個Spring內置的Bean,其中就包括AutowiredAnnotationBeanPostProcessor。若是想詳細瞭解Spring容器的啓動過程,能夠參考筆者的另外一篇文章:Spring源碼系列之容器啓動流程public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) {
// 省略部分代碼...
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
// 註冊AutowiredAnnotationBeanPostProcessor,這個bean的後置處理器用來處理@Autowired的注入
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 註冊CommonAnnotationBeanPostProcessor,用來處理如@Resource等符合JSR-250規範的註解
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
return beanDefs;
}
複製代碼
AutowiredAnnotationBeanPostProcessor是什麼時候被調用的呢?數組
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 執行後置處理器,填充屬性,完成自動裝配
// 在這裏會調用到AutowiredAnnotationBeanPostProcessor
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
}
}
複製代碼
public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
// 解析出bean中帶有@Autowired註解、@Inject和@Value註解的屬性和方法
// 對於本文的demo而言,在此處就會解析出OrderServiceImpl類上的userService屬性
// 至於如何解析的,findAutowiringMetadata()方法比較複雜,這裏就不展開了,Spring中提供了不少對註解等元數據信息讀取的方法,進行了大量的封裝。
// 若是不是本身親自參與開發Spring的話,很難摸透它封裝的那些數據結構。
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 自動裝配,實現依賴注入
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
複製代碼
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
複製代碼
public AutowiredAnnotationBeanPostProcessor() {
// 添加@Autowired
this.autowiredAnnotationTypes.add(Autowired.class);
// 添加@Value
this.autowiredAnnotationTypes.add(Value.class);
try {
// 若是項目中引入了JSR-330相關的jar包,那麼就會添加@Inject
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
}
}
複製代碼
beanFactory.resolveDependency()
。protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
// 判斷緩存(第一次注入userService的時候,確定沒有緩存,因此會進入到else裏面)
// 當第一次注入完成後,會將userService緩存到cachedFieldValue這個屬性中,
// 這樣當其餘的類一樣須要注入userService時,就會從這兒的緩存當中讀取了。
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
// 經過beanFactory.resolveDependency()方法,來從容器中找到userService屬性對應的值。
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
// 省略部分代碼...
// 省略的這部分代碼就是將value進行緩存,緩存到cachedFieldValue屬性中
}
if (value != null) {
// 經過Java的反射,爲屬性進行復制
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
複製代碼
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
// 省略部分不重要的代碼...
// 屬性的類型多是數組、集合、Map類型,因此這一步是處理數組類型、Collection、Map類型的屬性
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 根據須要注入的類型type,從容器中找到有哪些匹配的Bean。
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
// 若是從容器中沒有找到,且@Autowired的required屬性爲true,那麼則會拋出異常
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 先根據類型匹配出能夠依賴注入的bean的Class,若是匹配出多個,則再根據屬性名匹配
if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
// 當匹配到多個bean的Class,可是殊不知道要選擇哪個注入時,就會拋出異常
return descriptor.resolveNotUnique(type, matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
// 只匹配到一個,則就使用匹配到這個類型
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
// 此處instanceCandidate = UserServiceImpl.class
if (instanceCandidate instanceof Class) {
// instanceCandidate是注入屬性的類型,這個須要根據Class,經過FactoryBean的getBean()方法,建立該類型的單例bean
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
// 若是沒從容器中找到對應的bean,則須要判斷屬性值是不是必須注入的,
// 即@Autowired(required=false/true),若是爲true,則拋異常,這就是常常項目啓動時,咱們看到的異常
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
複製代碼
@Autowired
private UserService[] userServiceArray;
@Autowired
private List<UserService> userServiceList;
@Autowired
private Map<String,UserService> userServiceMap;
複製代碼
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
Class<?> type = descriptor.getDependencyType();
// 處理數組類型
if (type.isArray()) {
// findAutowireCandidates最終會調用getBean()方法
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
new MultiElementDescriptor(descriptor));
return result;
}
// 處理集合類型
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
// findAutowireCandidates最終會調用getBean()方法
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
new MultiElementDescriptor(descriptor));
return result;
}
// 處理Map類型
else if (Map.class == type) {
// findAutowireCandidates最終會調用getBean()方法
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
new MultiElementDescriptor(descriptor));
return matchingBeans;
}
else {
return null;
}
}
複製代碼
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
複製代碼
NoSuchBeanDefinitionException
。// 若是容器彙總沒有找到指定類型的bean,那麼matchingBeans屬性就是空的
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
// 拋出異常
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
複製代碼
if (matchingBeans.size() > 1) {
// 判斷應該使用哪個bean
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
// 當匹配到多個bean的Class,可是殊不知道要選擇哪個注入時,就會拋出異常
return descriptor.resolveNotUnique(type, matchingBeans);
}
else {
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
複製代碼
NoUniqueBeanDefinitionException
。"expected single matching bean but found " + beanNamesFound.size() + ": " + StringUtils.collectionToCommaDelimitedString(beanNamesFound)
複製代碼
NoUniqueBeanDefinitionException
異常。這就是咱們日常所說的@Autowired註解是先根據類型注入,當碰到多個相同類型時,就會根據屬性名注入。它的實現原理就是在以下代碼中實現的。
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
// 根據Primary註解來決定優先注入哪一個bean
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
// 根據@Priority註解的優先級來決定注入哪一個bean
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// 若是既沒有指定@Primary,也沒有指定@Priority,那麼就會根據屬性的名稱來決定注入哪一個bean
// 若是要注入的屬性的名稱與Bean的beanName相同或者別名相同,那麼會就會優先注入這個Bean
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
// 前面三種狀況都沒有肯定要注入哪一個bean,那麼就返回null。當返回null時,那麼就會再調用該方法出拋出異常。
return null;
}
複製代碼
AutowiredFeildElement.inject()
方法中,經過反射進行注入,完成自動裝配。在文章的開頭,我問了一個問題:自動裝配的模型是什麼?有哪幾種?和Autowired註解有什麼關聯?實際上這個問題,和今天的主角AutowiredAnnotationBeanPostProcessor沒有任何關係。可是爲何又把它放在這篇文章中提出來呢?這是由於@Autowired註解的實現原理和自動裝配模型極爲容易混淆。緩存
public enum Autowire {
NO(AutowireCapableBeanFactory.AUTOWIRE_NO),
BY_NAME(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME),
BY_TYPE(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE);
}
複製代碼
<bean id="orderService" class="com.tiantang.study.service.impl.OrderServiceImpl" autowire="byName">
</bean>
複製代碼
@Bean(autowire = Autowire.BY_NAME)
public OrderService orderService(){
return new OrderServiceImpl();
}
複製代碼
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 判斷bean的注入模型是byName,仍是byType。
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 對於MyBatis而言,Mapper在實例化以後,會填充屬性,這個時候,須要找到MapperFactoryBean有哪些屬性須要填充
// 在Mapper的BeanDefinition初始化時,默認添加了一個屬性,addToConfig
// 在下面的if邏輯中,執行完autowireByType()方法後,會找出另外另個須要填充的屬性,分別是sqlSessionFactory和sqlSessionTemplate
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 第六次執行後置處理器,填充屬性,完成自動裝配
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
if (pvs != null) {
// 實現經過byName或者byType類型的屬性注入
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
複製代碼
// 判斷bean的注入模型是byName,仍是byType。
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 對於MyBatis而言,Mapper在實例化以後,會填充屬性,這個時候,須要找到MapperFactoryBean有哪些屬性須要填充
// 在Mapper的BeanDefinition初始化時,默認添加了一個屬性,addToConfig
// 在下面的if邏輯中,執行完autowireByType()方法後,會找出另外另個須要填充的屬性,分別是sqlSessionFactory和sqlSessionTemplate
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
複製代碼
applyPropertyValues()
方法,而後將其填充到Bean當中。sqlSessionFactory
、sqlSessionTemplate
,而後爲這兩個屬性賦值。private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
GenericBeanDefinition definition;
for (BeanDefinitionHolder holder : beanDefinitions) {
definition = (GenericBeanDefinition) holder.getBeanDefinition();
// 指定MapperFactoryBean的自動裝配模型爲AUTOWIRE_BY_TYPE
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
}
}
複製代碼
總結以前,先回答一下文章開頭的三個問題。1)@Autowired註解的實現是經過後置處理器AutowiredAnnotationBeanPostProcessor類的postProcessPropertyValues()方法實現的。2)當自動裝配時,從容器中若是發現有多個同類型的屬性時,@Autowired註解會先根據類型判斷,而後根據@Primary、@Priority註解判斷,最後根據屬性名與beanName是否相等來判斷,若是仍是不能決定注入哪個bean時,就會拋出NoUniqueBeanDefinitionException異常。3)@Autowired自動裝配中byName、byType與自動裝配的模型中的byName、byTYpe沒有任何關係,二者含義徹底不同,前者是實現技術的手段,後者是用來定義BeanDefiniton中autowireMode屬性的值的類型。微信
相關推薦數據結構