重拾-Spring IOC

为何重拾

使用了 Spring 多年,但是对其底层的一些实现还是一知半解,一些概念比较模糊;故决定重新拾起,加深对 Spring 的认识。

重拾计划

spring 版本说明

Spring 在经过多年的演进过程中,其功能越来越丰富,组件越来越多;为了避免在阅读源码的过程中深陷泥潭中,决定采用最原始的版本 1.0; 但又不局限于 1.0 版本。

spring ioc

spring aop

spring 事务管理

spring orm 集成

实现分析

Spring 容器启动

在本文中,通过常用的构造 ClassPathXmlApplicationContext 实例来作为对 Spring 实现分析的入口

    ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

通过调用链追踪,Spring 容器启动核心操作由 AbstractApplicationContext 类中 refresh 方法实现

public void refresh() throws BeansException {
    this.startupTime = System.currentTimeMillis();

    // tell subclass to refresh the internal bean factory
    // 完成 xml 配置文件的解析, 解析 bean 标签生成 BeanDefinition 对象,并注册到 BeanFactory
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();

    // configure the bean factory with context semantics
    beanFactory.registerCustomEditor(Resource.class, new ContextResourceEditor(this));
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    beanFactory.ignoreDependencyType(ResourceLoader.class);
    beanFactory.ignoreDependencyType(ApplicationContext.class);
    postProcessBeanFactory(beanFactory);

    // invoke factory processors registered with the context instance
    // 获取内置 BeanFactoryPostProcessor 实例,并遍历调用 postProcessBeanFactory 方法
    // 对 BeanFactory 进行后置处理
    for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) {
        BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();
        factoryProcessor.postProcessBeanFactory(beanFactory);
    }

    if (getBeanDefinitionCount() == 0) {
        logger.warn("No beans defined in ApplicationContext [" + getDisplayName() + "]");
    }
    else {
        logger.info(getBeanDefinitionCount() + " beans defined in ApplicationContext [" + getDisplayName() + "]");
    }

    // invoke factory processors registered as beans in the context
    // 从 Bean Definition 集合中查找 BeanFactoryPostProcessor 定义并实例化
    // 获取 BeanFactoryPostProcessor 实例,并遍历调用 postProcessBeanFactory 方法
    // 对 BeanFactory 进行后置处理
    invokeBeanFactoryPostProcessors();

    // register bean processor that intercept bean creation
    // 从 Bean Definition 集合中查找 BeanPostProcessor 类定义实例化并注册到 BeanFactory 中
    registerBeanPostProcessors();

    // initialize message source for this context
    initMessageSource();

    // initialize other special beans in specific context subclasses
    onRefresh();

    // check for listener beans and register them
    refreshListeners();

    // instantiate singletons this late to allow them to access the message source
    // 对 Bean Definition 中单例且非延迟加载的类型进行实例化
    /**
     * bean 初始化过程如下:
     * 1 : bean 构造初始化
     * 2 : bean 属性注入 (通过 bean definition 中的 property , autowire(byType, byName) 实现)
     * 3 : bean 若实现 BeanNameAware 接口,调用 setBeanName() 方法
     * 4 : bean 若实现 BeanFactoryAware 接口, 调用 setBeanFactory() 方法
     * 5 : 遍历调用 BeanFactory 中注册的 BeanPostProcessor 实例的 postProcessorBeforeInitialization() 方法
     * 6 : bean 若实现了 InitializingBean 接口,调用 afterPropertiesSet() 方法
     * 7 : bean 实例对应的 bean definition 中若定义了 init-method 属性则调用对应的 init 方法
     * 8 : 遍历调用 BeanFactory 中注册的 BeanPostProcessor 实例的 postProcessorAfterInitialization() 方法
     */
    beanFactory.preInstantiateSingletons();

    // last step: publish respective event
    publishEvent(new ContextRefreshedEvent(this));
}

从源码中可知,Spring 容器在启动过程中,主要完成以下流程 :

  • 通过加载指定的配置文件,完成 Bean Definition 解析并注册到 BeanFactory 实例中
  • 通过内置及应用自定义的 BeanFactoryPostProcessor 对 BeanFactory 实例进行后置处理
  • 实例化应用自定义的 BeanPostProcessor 并注册到 BeanFactory 实例中
  • 实例化 Spring 容器中的 Bean

Spring 容器关闭

public void close() {
    logger.info("Closing application context [" + getDisplayName() + "]");

    // destroy all cached singletons in this context,
    // invoking DisposableBean.destroy and/or "destroy-method"
    // 销毁容器中缓存的单例对象实例
    // 执行容器中 DisposableBean 的 destroy 方法
    getBeanFactory().destroySingletons();

    // publish respective event
    // 发送 spring 上下文关闭事件
    publishEvent(new ContextClosedEvent(this));
}

通过调用链追踪,Spring 会遍历容器中缓存的 bean 实例调用 destroyBean 方法。

protected void destroyBean(String beanName, Object bean) {
    logger.debug("Retrieving depending beans for bean '" + beanName + "'");
    // 先销毁所有依赖当前 bean 的实例
    String[] dependingBeans = getDependingBeanNames(beanName);
    if (dependingBeans != null) {
        for (int i = 0; i < dependingBeans.length; i++) {
            destroySingleton(dependingBeans[i]);
        }
    }

    if (bean instanceof DisposableBean) {
        // 如果 bean 实现了 DisposableBean 接口,将会执行 destroy 方法
        logger.debug("Calling destroy() on bean with name '" + beanName + "'");
        try {
            ((DisposableBean) bean).destroy();
        }
        catch (Exception ex) {
            logger.error("destroy() on bean with name '" + beanName + "' threw an exception", ex);
        }
    }

    try {
        RootBeanDefinition bd = getMergedBeanDefinition(beanName, false);
        if (bd.getDestroyMethodName() != null) {
            // 如果 bean 定义了 destroy-method 属性,将会调用自定义的销毁方法
            logger.debug("Calling custom destroy method '" + bd.getDestroyMethodName() +
                                     "' on bean with name '" + beanName + "'");
            invokeCustomDestroyMethod(beanName, bean, bd.getDestroyMethodName());
        }
    }
    catch (NoSuchBeanDefinitionException ex) {
        // ignore, from manually registered singleton
    }
}

下面将针对 Spring Bean 在容器启动过程中的各个环节的实现进行详细说明

Spring Bean 定义解析

通过对 refreshBeanFactory 方法的调用链追踪,可以看到在 DefaultXmlBeanDefinitonParser 类的 registerBeanDefinitions 方法中实现对 Spring Bean 定义的解析及注册。

public void registerBeanDefinitions(BeanDefinitionRegistry beanFactory, ClassLoader beanClassLoader,
                                                                            Document doc, Resource resource) {
    this.beanFactory = beanFactory;
    this.beanClassLoader = beanClassLoader;
    this.resource = resource;

    logger.debug("Loading bean definitions");
    Element root = doc.getDocumentElement();

    this.defaultLazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
    logger.debug("Default lazy init '" + this.defaultLazyInit + "'");
    this.defaultDependencyCheck = root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE);
    logger.debug("Default dependency check '" + this.defaultDependencyCheck + "'");
    this.defaultAutowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);
    logger.debug("Default autowire '" + this.defaultAutowire + "'");

    NodeList nl = root.getChildNodes();
    int beanDefinitionCounter = 0;
    for (int i = 0; i < nl.getLength(); i++) {
        Node node = nl.item(i);
        if (node instanceof Element && BEAN_ELEMENT.equals(node.getNodeName())) {
            beanDefinitionCounter++;
            loadBeanDefinition((Element) node);
        }
    }
    logger.debug("Found " + beanDefinitionCounter + " <" + BEAN_ELEMENT + "> elements defining beans");
}
protected void loadBeanDefinition(Element ele) {
    // 获取 bean 的 id, name 属性
    String id = ele.getAttribute(ID_ATTRIBUTE);
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    List aliases = new ArrayList();
    if (nameAttr != null && !"".equals(nameAttr)) {
        String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS, true, true);
        aliases.addAll(Arrays.asList(nameArr));
    }

    if (id == null || "".equals(id) && !aliases.isEmpty()) {
        id = (String) aliases.remove(0);
        logger.debug("No XML 'id' specified - using '" + id + "' as ID and " + aliases + " as aliases");
    }

    // 解析 bean 标签, 获取 bean 配置的属性,构造,是否懒加载 作用域
    AbstractBeanDefinition beanDefinition = parseBeanDefinition(ele, id);

    if (id == null || "".equals(id)) {
        if (beanDefinition instanceof RootBeanDefinition) {
            id = ((RootBeanDefinition) beanDefinition).getBeanClassName();
            logger.debug("Neither XML 'id' nor 'name' specified - using bean class name [" + id + "] as ID");
        }
        else {
            throw new BeanDefinitionStoreException(this.resource, "","Child bean definition has neither 'id' nor 'name'");
        }
    }

    logger.debug("Registering bean definition with id '" + id + "'");
    // 将 bean definiton 注册到 beanFactory
    this.beanFactory.registerBeanDefinition(id, beanDefinition);
    for (Iterator it = aliases.iterator(); it.hasNext();) {
        this.beanFactory.registerAlias(id, (String) it.next());
    }
}
protected AbstractBeanDefinition parseBeanDefinition(Element ele, String beanName) {
    String className = null;
    try {
        // 获取 class 属性
        if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
            className = ele.getAttribute(CLASS_ATTRIBUTE);
        }
        String parent = null;
        if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
            parent = ele.getAttribute(PARENT_ATTRIBUTE);
        }
        if (className == null && parent == null) {
            throw new BeanDefinitionStoreException(this.resource, beanName, "Either 'class' or 'parent' is required");
        }

        AbstractBeanDefinition bd = null;
        // 获取属性
        MutablePropertyValues pvs = getPropertyValueSubElements(beanName, ele);

        if (className != null) {
            // 获取构造
            ConstructorArgumentValues cargs = getConstructorArgSubElements(beanName, ele);
            RootBeanDefinition rbd = null;

            if (this.beanClassLoader != null) {
                Class clazz = Class.forName(className, true, this.beanClassLoader);
                rbd = new RootBeanDefinition(clazz, cargs, pvs);
            }
            else {
                rbd = new RootBeanDefinition(className, cargs, pvs);
            }
            // 设置 bean dependOn
            if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
                String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
                rbd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, BEAN_NAME_DELIMITERS, true, true));
            }

            String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
            if (DEFAULT_VALUE.equals(dependencyCheck)) {
                dependencyCheck = this.defaultDependencyCheck;
            }
            rbd.setDependencyCheck(getDependencyCheck(dependencyCheck));

            // 设置 bean 自动注册的方式 byType, byName or none
            String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
            if (DEFAULT_VALUE.equals(autowire)) {
                autowire = this.defaultAutowire;
            }
            rbd.setAutowireMode(getAutowireMode(autowire));

            // 设置 bean 的 init-method
            String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
            if (!initMethodName.equals("")) {
                rbd.setInitMethodName(initMethodName);
            }

            // 设置 bean 的 destroy-method
            String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
            if (!destroyMethodName.equals("")) {
                rbd.setDestroyMethodName(destroyMethodName);
            }

            bd = rbd;
        }
        else {
            bd = new ChildBeanDefinition(parent, pvs);
        }

        // 设置 bean 是否为单例
        if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
            bd.setSingleton(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)));
        }

        // 是否懒加载
        String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
        if (DEFAULT_VALUE.equals(lazyInit) && bd.isSingleton()) {
            // just apply default to singletons, as lazy-init has no meaning for prototypes
            lazyInit = this.defaultLazyInit;
        }
        bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

        bd.setResourceDescription(this.resource.getDescription());

        return bd;
    }
    catch (ClassNotFoundException ex) {
    }
    catch (NoClassDefFoundError err) {}
}

Spring 容器在将配置文件加载后,会解析 bean 标签并通过其相应的属性配置构造 BeanDefinition 对象,然后将 BeanDefinition 对象注册添加到 BeanFactory 中。

Spring Bean 实例化

public void preInstantiateSingletons() {
    if (logger.isInfoEnabled()) {
        logger.info("Pre-instantiating singletons in factory [" + this + "]");
    }
    // 遍历注册的 bean definition
    for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext();) {
        String beanName = (String) it.next();
        if (containsBeanDefinition(beanName)) {
            RootBeanDefinition bd = getMergedBeanDefinition(beanName, false);
            // 如果 bean 定义为单例且非延迟加载的
            if (bd.isSingleton() && !bd.isLazyInit()) {
                // 判断 bean 是否为 FactoryBean
                if (FactoryBean.class.isAssignableFrom(bd.getBeanClass())) {
                    FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
                    if (factory.isSingleton()) {
                        getBean(beanName);
                    }
                }
                else {
                    // 若是普通 bean 则调用 getBean
                    getBean(beanName);
                }
            }
        }
    }
}
public Object getBean(String name) throws BeansException {
    String beanName = transformedBeanName(name);
    // eagerly check singleton cache for manually registered singletons
    // 检查单例缓存池中 是否存在 bean 实例,如果有从缓存中获取 bean 实例
    Object sharedInstance = this.singletonCache.get(beanName);
    if (sharedInstance != null) {
        if (logger.isDebugEnabled()) {
            logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
        }
        return getObjectForSharedInstance(name, sharedInstance);
    }
    else {
        // check if bean definition exists
        RootBeanDefinition mergedBeanDefinition = null;
        try {
            mergedBeanDefinition = getMergedBeanDefinition(beanName, false);
        }
        catch (NoSuchBeanDefinitionException ex) {
            // not found -> check parent
            if (this.parentBeanFactory != null) {
                return this.parentBeanFactory.getBean(name);
            }
            throw ex;
        }
        // create bean instance
        if (mergedBeanDefinition.isSingleton()) {
            synchronized (this.singletonCache) {
                // re-check singleton cache within synchronized block
                sharedInstance = this.singletonCache.get(beanName);
                if (sharedInstance == null) {
                    logger.info("Creating shared instance of singleton bean '" + beanName + "'");
                    sharedInstance = createBean(beanName, mergedBeanDefinition);
                    addSingleton(beanName, sharedInstance);
                }
            }
            return getObjectForSharedInstance(name, sharedInstance);
        }
        else {
            return createBean(name, mergedBeanDefinition);
        }
    }
}
protected Object createBean(String beanName, RootBeanDefinition mergedBeanDefinition) throws BeansException {
    if (mergedBeanDefinition.getDependsOn() != null) {
        for (int i = 0; i < mergedBeanDefinition.getDependsOn().length; i++) {
            // guarantee initialization of beans that the current one depends on
            getBean(mergedBeanDefinition.getDependsOn()[i]);
        }
    }

    // bean 初始化并包装,也就是 new
    BeanWrapper instanceWrapper = null;
    if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
            mergedBeanDefinition.hasConstructorArgumentValues()) {
        instanceWrapper = autowireConstructor(beanName, mergedBeanDefinition);
    }
    else {
        instanceWrapper = new BeanWrapperImpl(mergedBeanDefinition.getBeanClass());
        initBeanWrapper(instanceWrapper);
    }
    Object bean = instanceWrapper.getWrappedInstance();

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    if (mergedBeanDefinition.isSingleton()) {
        // 单例的bean 则添加到缓存中
        addSingleton(beanName, bean);
    }
    // bean 属性注入
    populateBean(beanName, mergedBeanDefinition, instanceWrapper);

    try {
        if (bean instanceof BeanNameAware) {
            // bean 若实现接口 BeanNameAware 则调用 setBeanName 方法
            ((BeanNameAware) bean).setBeanName(beanName);
        }

        if (bean instanceof BeanFactoryAware) {
            // bean 若实现接口 BeanFactoryAware 则调用 setBeanFactory 方法
            ((BeanFactoryAware) bean).setBeanFactory(this);
        }

        // 调用 BeanPostProcessor 执行 postProcessBeforeInitialization 方法
        bean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        // 若 bean 实现 InitializingBean 接口则执行 afterPropertiesSet 方法
        // 若 bean 定义中定义了 init-method 属性则执行对应的init 方法
        invokeInitMethods(bean, beanName, mergedBeanDefinition);
        // 调用 BeanPostProcessor 执行 postProcessAfterInitialization 方法
        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
    }
    catch (InvocationTargetException ex) {
        throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName,
                                                                        "Initialization of bean failed", ex.getTargetException());
    }
    catch (Exception ex) {
        throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName,
                                                                        "Initialization of bean failed", ex);
    }
    return bean;
}

从 bean 的实例化过程中,Spring 容器在启动时只针对单例且非延迟加载的 bean 进行初始化;其他的 bean 只有在显示调用 getBean() 方法时才去实例化;下面将会对实例化过程中的详细过程进行说明。

Spring Bean 作用域

singleton 单例模式

Spring IoC 容器中只会存在一个共享的Bean实例,无论有多少个Bean引用它,始终指向同一对象。

    <bean id="test" singleton="true" />

    <bean scope="singleton" />

Spring 1.0 中通过 bean 定义属性 singleton='true' 表示单例; 在 Spring 2.x 之后版本改为定义属性 scope='singleton', 同时兼容 1.0 的配置

prototype 原型模式

每次通过Spring容器获取prototype定义的bean时,容器都将创建一个新的Bean实例,每个Bean实例都有自己的属性和状态

    <bean id="test" singleton="false" />

    <bean scope="prototype" />

Spring 1.0 中通过 bean 定义属性 singleton='false' 表示原型模式; 在 Spring 2.x 之后版本改为定义属性 scope='prototype', 同时兼容 1.0 的配置

Spring Bean 生命周期

image
示例
public class LifecycleBean implements BeanNameAware, InitializingBean, BeanFactoryAware, ResourceLoaderAware, ApplicationContextAware, DisposableBean {

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("set bean factory");
    }

    public void setBeanName(String name) {
        System.out.println("set bean name");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("Initializing Bean afterPropertiesSet");
    }

    public void setApplicationContext(ApplicationContext context) throws BeansException {
        System.out.println("set application context");
    }

    public void setResourceLoader(ResourceLoader resourceLoader) {
        System.out.println("set resource loader");
    }

    public void init () {
        System.out.println("do init method");
    }

    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
        System.out.println("post Process Before Initialization");
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
        System.out.println("post Process After Initialization");
        return bean;
    }

    public void destroy() throws Exception {
        System.out.println("do destroy ");
    }

    public void destroyMethod() throws Exception {
        System.out.println("do destroy method");
    }
}

public class PostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
        if (bean instanceof LifecycleBean) {
            ((LifecycleBean) bean).postProcessBeforeInitialization(bean, name);
        }
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
        if (bean instanceof LifecycleBean) {
            ((LifecycleBean) bean).postProcessAfterInitialization(bean, name);
        }
        return bean;
    }
}

spring 配置文件如下

<beans>
    <bean id="lifecycleBean" class="org.springframework.beans.factory.LifecycleBean" init-method="init" />

    <bean id="postProcessor" class="org.springframework.beans.factory.PostProcessor" />
</beans>

运行结果如下:


set bean name
set bean factory
set resource loader
set application context
post Process Before Initialization
Initializing Bean afterPropertiesSet
do init method
post Process After Initialization
do destroy 
do destroy method

Spring Bean 注入方式

构造注入
<bean>
    <constructor-arg index="1">
        <value></value>
    </constructor-arg>
</bean>

<bean autowire="constructor" />

当 bean 定义配置如以上方式的时候,会触发 autowireConstructor (详细实现参考源码吧)

BeanWrapper instanceWrapper = null;
if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
        mergedBeanDefinition.hasConstructorArgumentValues()) {

    instanceWrapper = autowireConstructor(beanName, mergedBeanDefinition);
}
byType 注入
<bean autowire="byType" />

当 bean 定义配置如以上方式的时候,会触发 autowireByType 如下:

protected void autowireByType(String beanName, RootBeanDefinition mergedBeanDefinition,
                                                                BeanWrapper bw, MutablePropertyValues pvs) {
    // 查找 bean 存在可写方法的非基本数据类型的成员变量
    String[] propertyNames = unsatisfiedObjectProperties(mergedBeanDefinition, bw);
    for (int i = 0; i < propertyNames.length; i++) {
        String propertyName = propertyNames[i];
        // look for a matching type
        // 获取成员变量的类型
        Class requiredType = bw.getPropertyDescriptor(propertyName).getPropertyType();
        // 查找成员变量对应的 bean 实例
        Map matchingBeans = findMatchingBeans(requiredType);
        if (matchingBeans != null && matchingBeans.size() == 1) {
            // 成员变量查找到匹配的bean实例,有且只有一个的时候
            // 将属性名和属性值 添加到 PropertyValues 中
            pvs.addPropertyValue(propertyName, matchingBeans.values().iterator().next());
            if (logger.isDebugEnabled()) {
                logger.debug("Autowiring by type from bean name '" + beanName +
                                        "' via property '" + propertyName + "' to bean named '" +
                                        matchingBeans.keySet().iterator().next() + "'");
            }
        }
        else if (matchingBeans != null && matchingBeans.size() > 1) {
            // 当存在多个同类型的实例时 抛出异常
            throw new UnsatisfiedDependencyException(beanName, propertyName,
                    "There are " + matchingBeans.size() + " beans of type [" + requiredType + "] for autowire by type. " +
                    "There should have been 1 to be able to autowire property '" + propertyName + "' of bean '" + beanName + "'.");
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Not autowiring property '" + propertyName + "' of bean '" + beanName +
                                        "' by type: no matching bean found");
            }
        }
    }
}
byName 注入
<bean autowire="byName" />

当 bean 定义配置如以上方式的时候,会触发 autowireByName 如下:

protected void autowireByName(String beanName, RootBeanDefinition mergedBeanDefinition,
                                                                BeanWrapper bw, MutablePropertyValues pvs) {
    // 查找 bean 存在可写方法的非基本数据类型的成员变量
    String[] propertyNames = unsatisfiedObjectProperties(mergedBeanDefinition, bw);
    for (int i = 0; i < propertyNames.length; i++) {
        String propertyName = propertyNames[i];
        // 在 Spring 容器中查找是否存在以 propertyName 命名的 bean definition
        if (containsBean(propertyName)) {
            // 实例化依赖的 bean, 并添加到 MutablePropertyValues 中
            Object bean = getBean(propertyName);
            pvs.addPropertyValue(propertyName, bean);
            if (logger.isDebugEnabled()) {
                logger.debug("Added autowiring by name from bean name '" + beanName +
                    "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
            }
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Not autowiring property '" + propertyName + "' of bean '" + beanName +
                                        "' by name: no matching bean found");
            }
        }
    }
}
set 注入
<bean>
    <property name="age">
        <value>11</value>
    </property>
</bean>

当 bean 定义配置如上,或者采用 byName, byType 的注入方式时,都会调用 applyPropertyValues 方法完成属性的注入。(详细实现参考源码吧)

Spring Bean 注解式注入

自 Spring 2.5 版本之后,支持通过注解方式实现 Bean 的自动注入,譬如 @Autowired, @Resource 等注解

为了引入注解式自动注入, Spring 在 2.x 版本中新增了 InstantiationAwareBeanPostProcessor 接口,该接口继承 BeanPostProcessor 并新增了方法 postProcessPropertyValues ; 该方法主要实现

Post-process the given property values before the factory applies them to the given bean
Autowired 注解

采用 Autowired 注解实现自动注入,需在配置文件中配置 AutowiredAnnotationBeanPostProcessor Bean

public AutowiredAnnotationBeanPostProcessor() {
    this.autowiredAnnotationTypes.add(Autowired.class);
    this.autowiredAnnotationTypes.add(Value.class);
    ClassLoader cl = AutowiredAnnotationBeanPostProcessor.class.getClassLoader();
    try {
        this.autowiredAnnotationTypes.add((Class<? extends Annotation>) cl.loadClass("javax.inject.Inject"));
        logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
    }
    catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}

AutowiredAnnotationBeanPostProcessor 构造可以看出其支持 @Autowired,@Value,@Inject 注解的自动注入。 下面大概看下其如何实现自动注入

public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
    // 查找 bean 中需要自动注入的元数据,包括 field, method
    InjectionMetadata metadata = findAutowiringMetadata(bean.getClass());
    try {
        // 实现注入
        metadata.inject(bean, beanName, pvs);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
}
Resource 注解

采用 Resource 注解实现自动注入,需在配置文件中配置 CommonAnnotationBeanPostProcessor Bean

public CommonAnnotationBeanPostProcessor() {
    setOrder(Ordered.LOWEST_PRECEDENCE - 3);
    setInitAnnotationType(PostConstruct.class);
    setDestroyAnnotationType(PreDestroy.class);
    ignoreResourceType("javax.xml.ws.WebServiceContext");
}

CommonAnnotationBeanPostProcessor 构造可以看出,该类同时支持对注解 @PostConstruct, @PreDestroy 生效。

public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
    // 查找 bean 中标注有 @Resource 注解的 Field, method
    InjectionMetadata metadata = findResourceMetadata(bean.getClass());
    try {
        // 实现注入
        metadata.inject(bean, beanName, pvs);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
    }
    return pvs;
}

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    // 查找 bean 定义中标注了 PostConstruct 注解的方法
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    try {
        // 调用指定 post construct method
        metadata.invokeInitMethods(bean, beanName);
    }
    catch (InvocationTargetException ex) {
        throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Couldn't invoke init method", ex);
    }
    return bean;
}

public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
    // 查找 bean 定义中标注了 PreDestroy 注解的方法
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    try {
        // 调用指定 destroy method
        metadata.invokeDestroyMethods(bean, beanName);
    }
    catch (InvocationTargetException ex) {
        String msg = "Invocation of destroy method failed on bean with name '" + beanName + "'";
        if (logger.isDebugEnabled()) {
            logger.warn(msg, ex.getTargetException());
        }
        else {
            logger.warn(msg + ": " + ex.getTargetException());
        }
    }
    catch (Throwable ex) {
        logger.error("Couldn't invoke destroy method on bean with name '" + beanName + "'", ex);
    }
}
private LifecycleMetadata buildLifecycleMetadata(Class clazz) {
    final boolean debug = logger.isDebugEnabled();
    LinkedList<LifecycleElement> initMethods = new LinkedList<LifecycleElement>();
    LinkedList<LifecycleElement> destroyMethods = new LinkedList<LifecycleElement>();
    Class<?> targetClass = clazz;

    do {
        LinkedList<LifecycleElement> currInitMethods = new LinkedList<LifecycleElement>();
        LinkedList<LifecycleElement> currDestroyMethods = new LinkedList<LifecycleElement>();
        // 遍历 bean 的所有方法
        for (Method method : targetClass.getDeclaredMethods()) {
            if (this.initAnnotationType != null) {
                // 判断 method 是否标注了 @PostConstruct 注解
                if (method.getAnnotation(this.initAnnotationType) != null) {
                    LifecycleElement element = new LifecycleElement(method);
                    currInitMethods.add(element);
                    if (debug) {
                        logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
                    }
                }
            }
            if (this.destroyAnnotationType != null) {
                // 判断 method 是否标注了 @PreDestroy 注解
                if (method.getAnnotation(this.destroyAnnotationType) != null) {
                    currDestroyMethods.add(new LifecycleElement(method));
                    if (debug) {
                        logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);
                    }
                }
            }
        }
        initMethods.addAll(0, currInitMethods);
        destroyMethods.addAll(currDestroyMethods);
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return new LifecycleMetadata(clazz, initMethods, destroyMethods);
}
<context: annotation-config>

为了简化 Spring 配置文件中的 bean 配置,Spring 提供了 <context: annotation-config> 标签自动加载 AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor 等 bean。

在 spring-context 包 resources/META-INF 下的 spring.handlers 文件中配置如下:


http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler

public class ContextNamespaceHandler extends NamespaceHandlerSupport {

    public void init() {
        registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
        registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
        registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
        registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
        registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
        registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
        registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
    }

}
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, Object source) {

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);

    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        // 加载注册 AutowiredAnnotationBeanPostProcessor
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        // 加载注册 RequiredAnnotationBeanPostProcessor
        RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        // 加载注册 CommonAnnotationBeanPostProcessor
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition();
        try {
            ClassLoader cl = AnnotationConfigUtils.class.getClassLoader();
            def.setBeanClass(cl.loadClass(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME));
        }
        catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                    "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
        }
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    return beanDefs;
}

可以看出在 Spring 启动时,通过解析 <context: annotation-config> 标签,完成对 CommonAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor 的加载注册,进而实现通过注解方式的自动注入。

小结

BeanFactory & ApplicationContext

image

BeanFactoryPostProcessor & BeanPostProcessor

  • BeanFactoryPostProcessorApplicationContext 在 BeanFactory 完成创建后对其进行后置处理的接口
  • BeanPostProcessorBeanFactory 在 Bean 完成实例化对其进行的后置处理接口

BeanFactory & FactoryBean

  • BeanFactory 是 Spring 框架底层的核心接口,其提供了创建 bean,获取 bean 等核心功能。
  • FactoryBean 是生产 bean 的一个模式,也就是以工厂模式的方式生产 bean。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容