资讯专栏INFORMATION COLUMN

重拾-Spring-IOC

GraphQuery / 3137人阅读

摘要:为何重拾使用了多年,但是对其底层的一些实现还是一知半解,一些概念比较模糊故决定重新拾起,加深对的认识。小结是在完成创建后对其进行后置处理的接口是在完成实例化对其进行的后置处理接口是框架底层的核心接口,其提供了创建,获取等核心功能。

为何重拾

使用了 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引用它,始终指向同一对象。
    

    

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

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

    

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

Spring Bean 生命周期

示例
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 配置文件如下


    

    

运行结果如下:

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 定义配置如以上方式的时候,会触发 autowireConstructor (详细实现参考源码吧)

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

    instanceWrapper = autowireConstructor(beanName, mergedBeanDefinition);
}
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 定义配置如以上方式的时候,会触发 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 注入

    
        11
    

当 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) 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 initMethods = new LinkedList();
    LinkedList destroyMethods = new LinkedList();
    Class targetClass = clazz;

    do {
        LinkedList currInitMethods = new LinkedList();
        LinkedList currDestroyMethods = new LinkedList();
        // 遍历 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);
}
为了简化 Spring 配置文件中的 bean 配置,Spring 提供了  标签自动加载 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 registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, Object source) {

    Set beanDefs = new LinkedHashSet(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 启动时,通过解析 标签,完成对 CommonAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor 的加载注册,进而实现通过注解方式的自动注入。

小结 BeanFactory & ApplicationContext

BeanFactoryPostProcessor & BeanPostProcessor

BeanFactoryPostProcessorApplicationContext 在 BeanFactory 完成创建后对其进行后置处理的接口

BeanPostProcessorBeanFactory 在 Bean 完成实例化对其进行的后置处理接口

BeanFactory & FactoryBean

BeanFactory 是 Spring 框架底层的核心接口,其提供了创建 bean,获取 bean 等核心功能。

FactoryBean 是生产 bean 的一个模式,也就是以工厂模式的方式生产 bean。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/73511.html

相关文章

  • 重拾css(1)——写在前边的话

    摘要:本系列文章重拾主要参考王福朋知多少,结合自己的理解和学习需要,修改或添加了一些内容,难免有失偏颇,仅供自我学习参考之用。 工作中或多或少的写一些css,但总感觉掌握的不够扎实,时而需要查阅一下知识点。我想,一方面跟缺少科班出身式的系统学习有关,另一方面也苦于一直未寻觅到一套合我胃口教程。直到我读到了王福朋css知多少系列文章,使我有了重新系统学习css的想法。 本系列文章(重拾css)...

    li21 评论0 收藏0
  • CSS魔法堂:重拾Border之——更广阔的遐想

    摘要:也就是说我们操作的几何公式中的未知变量,而具体的画图操作则由渲染引擎处理,而不是我们苦苦哀求设计师帮忙。 前言  当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-top-left/right-radius的水平半径之和大于元素宽度时,实际值会按比...

    lily_wang 评论0 收藏0
  • CSS魔法堂:重拾Border之——解构Border

    摘要:本系列将稍微深入探讨一下那个貌似没什么好玩的魔法堂重拾之解构魔法堂重拾之图片作边框魔法堂重拾之不仅仅是圆角魔法堂重拾之更广阔的遐想解构说起我们自然会想起,而由条紧紧包裹着的边组成,所以的最小操作单元是。 前言  当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现...

    lingdududu 评论0 收藏0
  • spring-ioc流程源码解析

    摘要:中的流程中的方法是启动加载整个容器的关键方法。此函数第一步将流转换成的,接下来就是解析,转换成的然后注册到中的一个中去。现在马上就要开始解析了,真正的解析就在方法,是指,标签就是此下的,所以会走。至此,的流程就走完了。 Spring中ioc的流程 AbstractApplicationContext 中的refresh()方法是启动加载整个容器的关键方法。 在refresh()方法中...

    zorpan 评论0 收藏0
  • 架构~微服务

    摘要:接下来继续介绍三种架构模式,分别是查询分离模式微服务模式多级缓存模式。分布式应用程序可以基于实现诸如数据发布订阅负载均衡命名服务分布式协调通知集群管理选举分布式锁和分布式队列等功能。 SpringCloud 分布式配置 SpringCloud 分布式配置 史上最简单的 SpringCloud 教程 | 第九篇: 服务链路追踪 (Spring Cloud Sleuth) 史上最简单的 S...

    xinhaip 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<