Spring IOC:Bean的生命周期解剖

1.Bean的创建

传统的bean创建是通过xml加载的,如下xml配置bean:

    <bean id="role1" class="com.wbg.springxmlbean.entity.Role">
       <!-- property元素是定义类的属性,name属性定义的是属性名称 value是值
        相当于:
        Role role=new Role();
        role.setId(1);
        role.setRoleName("高级工程师");
        role.setNote("重要人员");-->
        <property name="id" value="1"/>
        <property name="roleName" value="高级工程师"/>
        <property name="note" value="重要人员"/>
    </bean>

这里的大致流程是:加载——>解析——>创建实例——>使用——>销毁

我们知道,创建对象的方式有三种:1.直接new,2.通过反射,3.工厂模式

反射创建对象就是通过获取Class对象来获取实例化对象:

获取Class对象的三种方式:

a.Class clazz = Class.forName();

b.Class clazz = 类名.class;

c.Class clazz = 对象名.getClass();

获取构造方法来实例化对象:

Constructor ctor = clazz.getDeclareConstructor();

Object obj = ctor.newInstance();

2.bean的定义信息及对象创建

首先我们需要了解什么是对象的实例化。所谓对象实例化,具体分为对象的实例化和初始化;实例化就是在堆中开辟一块空间,属性都是默认值;初始化是进行属性填充(set方法)以及执行初始化方法(init-method)。

除了用xml配置,我们还可以用注解注入bean,这两种方式都定义了bean的信息,以及还有其他类型的配置文件,比如json都可以配置bean信息。Spring用“BeanDefinitionReader”定义相关规范的接口,来对配置文件进行解析,转换为“BeanDefinition”对象。所以如果要扩展解析配置文件,可以通过实现"BeanDefinitionReader"接口来进行解析转换。

有了bean的定义信息之后,我们要对bean进行相关的实例化工作,通过反射进行实例化以及初始化操作,完全对象创建。

BeanFactory”这个接口是Bean容器的一个根接口,这是为了提高可扩展性,常见的实现类是"DefaultListableBeanFactory",里面的接口包括了创建对象(反射),所以“BeanDefinition”是通过“BeanFactory”来完成创建对象的。在这个过程,可以对它做一些扩展操作,就是“PostProcessor”,有人叫它为增强器,也有人叫它后置处理器,它的本质就是进行扩展实现。所以在读取“BeanDefinition”的时候,会经过一系列的“beanFactoryPostProcessor”后置处理器,然后再由“BeanFactory”完成一系列的实例化操作。

比如我们在配置"dataSource"的bean 的时候,是这样的:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/sampledb" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}"" />
</bean>

我们需要把${}信息替换成我们具体的值,这个修改的操作就是在"PlaceholderConfigurerSupport"中进行转换的。

我们也可以自己去实现“beanFactoryPostProcessor”的扩展类来对“BeanDefinition”的定义信息进行修改。

3.bean的生命周期细节

其实通过上面,我们已经可以知道bean的生命周期了,具体是这样的:

首先实例化对象,然后填充对象属性,接着执行aware接口需要实现的方法,aware接口是为了方便通过Spring中的bean对象来获取对应容器中的相关属性值,比如我们可以通过实现BeanNameAware来获取beanName:

下一步就是执行BeanPostProcessor的before和after方法,在中间会执行“init-method”完成对象初始化,然后在after中来实现动态代理。可以通过jdk或者cglib来完成动态代理,是在“BeanPostProcessor”的实现类“AbstractAutoProxyCreator”中完成的,这里我们可以查看源码来证实给大家看。

首先这是BeanPostProcessor的两个方法,分别是前置和后置处理方法:

public interface BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

再去看AbstractAutoProxyCreator的“postProcessAfterInitialization()”方法

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            return this.wrapIfNecessary(bean, beanName, cacheKey);
        }
    }

    return bean;
}

继续往“wrapIfNecessary”这个方法看:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    } else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    } else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
        Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        } else {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
    } else {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
}

这里我们看到了“this.createProxy”这个方法,里面可以找到是通过ProxyFactory获取jdk或cglib代理来实现对象代理的。

最后就是销毁动作了,这个就是我们IOC的整个生命周期的细节。

posted @ 2020-11-08 20:24  Conwie  阅读(110)  评论(0编辑  收藏  举报