Spring default-autowire

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

猜你喜欢

转载自my.oschina.net/u/2302503/blog/1572449