default-autowire 主要使用有三种方式:constructor、byName、byType
constructor:
// 在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修改,需要注意,例如
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
byName:
Name指的是pullingService,通过setPullingService将对象pullingService注入
<bean id="pullingService" class="com.xiude.diamond.service.LongPullingService"></bean>
public void setPullingService(LongPullingService service) { this.longPullingService = service; }
byType:
Type指的是LongPullingService这个类型,会根据set方法中的参数类型匹配将pullingService注入。如果存在两个LongPullingService类型的对象,注入时因为不知道具体是pullingServiceA还是pullingServiceB报错:org.springframework.beans.factory.NoUniqueBeanDefinitionException
<bean id="pullingServiceA" class="com.xiude.diamond.service.LongPullingService"></bean> <bean id="pullingServiceB" class="com.xiude.diamond.service.LongPullingService"></bean>pullingServiceA
byName、byType都必须显式声明set方法,否则无法注入的。
这里分析下autowireByType、autowireByName,它们在AbstractAutowireCapableBeanFactory类
如果是byType,会根据LongPullingService 设置方法setLongPullingService,无论你自定义的setLongPullingServiceB都不会管用的,它只按照类型来set
<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 = null
@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的populateBean
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。
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阶段完成。