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阶段完成。