default-autowire 主要使用有三種方式:constructor、byName、byTypejava
// 在applicationContext.xml中添加 //<bean id="pullingService" class="com.xiude.diamond.service.LongPullingService"></bean> public class TaskServiceImpl implements TaskService { LongPullingService longPullingService; public TaskServiceImpl(LongPullingService service){ this.longPullingService = service; } @Override public void setLongPullName(String longPullServiceName) { longPullingService.setName(longPullServiceName); } @Override public void displayName() { System.out.println(longPullingService.getName()); } }
Spring會將實例化一個全局惟一的LongPullingService對象pullingService,經過Constructor傳入給longPullingService。這個pullingService可能被多個TaskServiceImpl引用,其字段可能會被多個TaskServiceImpl修改,須要注意,例如spring
TaskService serviceA = (TaskService)context.getBean("taskService"); serviceA.setLongPullName("serviceA"); serviceA.displayName(); //輸出結果:serviceA TaskService serviceB = (TaskService)context.getBean("taskService"); serviceB.setLongPullName("serviceB"); //全局惟一的LongPullService中Name被修改了 serviceA.displayName(); //輸出結果:serviceB
Name指的是pullingService,經過setPullingService將對象pullingService注入app
<bean id="pullingService" class="com.xiude.diamond.service.LongPullingService"></bean>
public void setPullingService(LongPullingService service) { this.longPullingService = service; }
Type指的是LongPullingService這個類型,會根據set方法中的參數類型匹配將pullingService注入。若是存在兩個LongPullingService類型的對象,注入時由於不知道具體是pullingServiceA仍是pullingServiceB報錯:org.springframework.beans.factory.NoUniqueBeanDefinitionExceptionide
<bean id="pullingServiceA" class="com.xiude.diamond.service.LongPullingService"></bean> <bean id="pullingServiceB" class="com.xiude.diamond.service.LongPullingService"></bean>pullingServiceA
byName、byType都必須顯式聲明set方法,不然沒法注入的。ui
這裏分析下autowireByType、autowireByName,它們在AbstractAutowireCapableBeanFactory類this
若是是byType,會根據LongPullingService 設置方法setLongPullingService,不管你自定義的setLongPullingServiceB都不會管用的,它只按照類型來setspa
<bean id="longPullingServiceA" class="com.xiude.diamond.service.LongPullingService"> <property name="name" value="BUFFON"/> </bean>
LongPullingService longPullingServiceA; public void setLongPullingServiceB(LongPullingService service) { this.longPullingServiceA = service; }
若是是byName,會提取出longPullingServiceB,可是找不到beanDefition=longPullingServiceB對象,這個判斷是下面兩個方法完成,若是沒找到,去parentBeanFactory找。都沒找到則設置longPullingServiceA失敗,longPullingServiceA = nullcode
@Override public boolean containsBeanDefinition(String beanName) { Assert.notNull(beanName, "Bean name must not be null"); return this.beanDefinitionMap.containsKey(beanName); } @Override public boolean containsSingleton(String beanName) { return this.singletonObjects.containsKey(beanName); }
那麼autowireByName是如何實現的,其入口在AbstractAutowireCapableBeanFactory的populateBeanorm
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; }
這裏會根據AUTOWIRE_BY_TYPE || AUTOWIRE_BY_NAME選擇不一樣的方法,對於autowire-by-name,首先經過反射機制從當前Bean中獲得須要注入的屬性名,而後使用這個屬性名向容器申請與之同名的Bean。xml
protected void autowireByName( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { //獲取到longPullingServiceA String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { if (containsBean(propertyName)) { //從AbstractBeanFactory中獲取Bean對象,若是Bean沒有實例化,createBean Object bean = getBean(propertyName); pvs.add(propertyName, bean); registerDependentBean(propertyName, beanName); } } }
首先向IOC容器的存儲類AbstractBeanFactory查找該Bean,若是沒有找到,從父容器中繼續尋找。這裏涉及到遞歸調用尋找Bean。
public boolean containsBean(String name) { String beanName = transformedBeanName(name); //從DefaultSingletonBeanRegistry中查找,ConcurrentHashMap<String, Object> singletonObjects負責存儲bean name --> bean instance 的映射; //DefaultListableBeanFactory中含有ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap if (containsSingleton(beanName) || containsBeanDefinition(beanName)) { return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name)); } // Not found -> check parent. BeanFactory parentBeanFactory = getParentBeanFactory(); return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name))); }
其次getBean(propertyName),這個接口是的實現就是觸發依賴注入,涉及到doGetBean-->doCreateBean等操做,最後會返回實例化對象,即bean=LongPullingService@1846。
最後registerDependentBean註冊longPullingServiceA的依賴與被依賴對象 之間映射關係
public void registerDependentBean(String beanName, String dependentBeanName) { // A quick check for an existing entry upfront, avoiding synchronization... String canonicalName = canonicalName(beanName); //taskServiceA中使用了longPullServiceA,因此dependentBeans含有taskServiceA,例如longPullServiceA--taskServiceA //dependentBeanMap存儲bean -- 依賴該bean的其餘bean Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName); if (dependentBeans != null && dependentBeans.contains(dependentBeanName)) { return; } // No entry yet -> fully synchronized manipulation of the dependentBeans Set synchronized (this.dependentBeanMap) { dependentBeans = this.dependentBeanMap.get(canonicalName); if (dependentBeans == null) { dependentBeans = new LinkedHashSet<String>(8); this.dependentBeanMap.put(canonicalName, dependentBeans); } dependentBeans.add(dependentBeanName); } //dependenciesForBeanMap存儲taskServiceA--longPullServiceA 的映射 synchronized (this.dependenciesForBeanMap) { Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName); if (dependenciesForBean == null) { dependenciesForBean = new LinkedHashSet<String>(8); this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean); } dependenciesForBean.add(canonicalName); } }
走到這一步,taskServiceA中的longPullServiceA對象依舊爲NULL,賦值在applyPropertyValues階段完成。