Spring 系列目錄(http://www.javashuo.com/article/p-kqecupyl-bm.html)html
(1) 環境準備java
public class Company { private Department department; private List<Employee> employees; public Company() { } public Company(Department department) { this.department = department; } public void setDepartment(Department department) { this.department = department; } public void setEmployees(List<Employee> employees) { this.employees = employees; } } public class Employee { private String name; public void setName(String name) { this.name = name; } } public class Department { private String name; public void setName(String name) { this.name = name; } }
(2) xml 配置git
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="company1" autowire="byName" class="com.github.binarylei.Company"/> <bean id="company2" autowire="byType" class="com.github.binarylei.Company"/> <bean id="company3" autowire="no" class="com.github.binarylei.Company"/> <bean id="company4" autowire="constructor" class="com.github.binarylei.Company"> <constructor-arg index="0" ref="department"/> </bean> <bean id="company5" autowire="default" class="com.github.binarylei.Company"/> <bean id="employee1" class="com.github.binarylei.spring.Employee"> <property name="name" value="employee1"/> </bean> <bean id="employee2" class="com.github.binarylei.spring.Employee"> <property name="name" value="employee2"/> </bean> <bean id="department" class="com.github.binarylei.spring.Department"> <property name="name" value="department"/> </bean> </beans>
(3) 測試一把github
@Test public void test() { DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(lbf); reader.loadBeanDefinitions(new ClassPathResource("spring-context-di.xml", getClass())); // 1. 名稱注入 Company companyByName = (Company) lbf.getBean("company1"); // 2. 類型注入,支持 List 方式注入,若是本地容器找到多個則直接拋出異常 Company companyByType = (Company) lbf.getBean("company2"); // 3. no Company companyByNo = (Company) lbf.getBean("company3"); // 4. 構造器注入 Company companyByConstructor = (Company) lbf.getBean("company4"); // 5. 默認 Company companyDefault = (Company) lbf.getBean("company5"); }
Spring 屬性注入在 populateBean 方法中完成,有兩種注入方式:beanName 或 type 兩種。spring
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { if (mbd.hasPropertyValues()) { throw new BeanCreationException("Cannot apply property values to null instance"); } else { return; } } // 1. 後置處理器 InstantiationAwareBeanPostProcessor,能夠先略過 boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; } // 2. 依賴查找。根據 beanName 或 type 查找可注入的屬性值。 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); 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); } if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); // 3. 後置處理器攔截,對屬性值進行處理 InstantiationAwareBeanPostProcessor PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } // 4. 依賴校驗。是否全部的字段已經所有匹配上了,根據須要是否要拋出異常 if (needsDepCheck) { if (filteredPds == null) { // 過濾不須要進行屬性注入的字段,如 String、BeanFactory... filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } // 5. 依賴注入。至些屬性已經所有準備好了,能夠進行屬性注入。 if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }
上面的代碼看這很複雜,其實拋開後置處理器 InstantiationAwareBeanPostProcessor 就作了三件事,其中屬性的查找,尤爲是根據類型的查找最爲複雜:app
參考:源碼分析
1 . 《Spring各類依賴注入註解的區別》:https://blog.csdn.net/gaohe7091/article/details/39319363post
天天用心記錄一點點。內容也許不重要,但習慣很重要!測試