Spring 源码(12)Spring Bean 的创建过程(3)
2022-05-11 13:50
726 查看
继续上一篇
Spring Bean的创建过程的解读,上一篇介绍了
Spring在创建过程中
doGetBean方法,在执行过程中会调用
getSingleton方法并且设置一个
lambda表达式,这个
lambda表达式是
ObjectFactory的实现,当调用这个接口的
getObject方法时就会执行到
createBean方法,在
createBean方法中会进行
bean类型的解析,并且会进行方法覆盖的设置,当我们配置了如:
lookup-method或者
replace-method方法的时候就会在创建
Bean的过程中设置一个
CGLIB的工厂类为
Bean的对象,当调用的时候就会触发
CGLIB的拦截器方法执行具体的
Bean的获取,如果是单例对象引用了多例对象,那么就会每次创建一个新的对象给调用的方法执行。
接下来继续解读
Spring创建
Bean的过程。
早期Bean的创建
在
createBean方法中有一段代码:
try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. // 解析提前实例化,使用InstantiationAwareBeanPostProcessor实现 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } }
点进去:
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. // 判断是否有InstantiationAwareBeanPostProcessor在容器中 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { // 执行前实例化 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { // 执行后置初始化 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean; }
这里判断了容器中如果有实现
InstantiationAwareBeanPostProcessor接口,那么就执行前置实例化,
InstantiationAwareBeanPostProcessor接口继承了
BeanPostProcessor,并且这个接口的方法跟
BeanPostProcessor非常相似,
InstantiationAwareBeanPostProcessor的接口一个是前置的实例化
postProcessBeforeInstantiation,一个是后置的实例化
postProcessAfterInstantiation,而
BeanPostProcessor的接口一个是前置初始化
postProcessBeforeInitialization,一个是后置初始化
postProcessAfterInitialization。
在
Spring中
Bean的创建分为实例化+初始化,当然还有属性填充,这里进行提前实例化其实就是给了一个扩展点,让对象可以提前创建,而不用再继续走
doCreateBean方法里面的复杂逻辑,这样的话就提供给用户能够自己控制对象的创建过程以及执行增强等操作。
那这个实例化增强类是何时放进Spring容器的呢?
答案很简单,
InstantiationAwareBeanPostProcessor是一个
BeanPostProcessor,那么自然也就是在注册
BeanPostProcessor时放进去的。
看源码:
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null"); // Remove from old position, if any // 先删除掉旧的 this.beanPostProcessors.remove(beanPostProcessor); // Track whether it is instantiation/destruction aware // 如果是InstantiationAwareBeanPostProcessor 设置属性 if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) { this.hasInstantiationAwareBeanPostProcessors = true; } // 设置销毁的标识位 if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) { this.hasDestructionAwareBeanPostProcessors = true; } // Add to end of list // 添加到链表尾 this.beanPostProcessors.add(beanPostProcessor); }
接下来试试提前实例化的案例:
InstantiationAwareBeanPostProcessor 实验
创建一个需要提前实例化的对象:
/** * @author <a href="https://www.cnblogs.com/redwinter/">redwinter</a> * @since 1.0 **/ public class MyBeforeInstantiation { public void beforeInvoke(){ System.out.println("提前实例化,开始执行业务...."); } }
创建一个
InstantiationAwareBeanPostProcessor的实现类:
/** * @author <a href="https://www.cnblogs.com/redwinter/">redwinter</a> * @since 1.0 **/ public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { System.out.println("beanName: " + beanName + "执行了 postProcessBeforeInstantiation 方法"); // 提前进行实例化 if (beanClass == MyBeforeInstantiation.class) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(beanClass); enhancer.setCallback(new MyMethodInterceptor()); Object obj = enhancer.create(); System.out.println("创建对象:" + obj); return obj; } return null; } @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { System.out.println("beanName: " + beanName + "执行了 postProcessAfterInstantiation 方法"); return false; } @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { System.out.println("beanName: " + beanName + "执行了 postProcessProperties 方法"); return pvs; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("beanName: " + beanName + "执行了 postProcessBeforeInitialization 方法"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("beanName: " + beanName + "执行了 postProcessAfterInitialization 方法"); return bean; } }
这里使用了CGLIB 动态代理去增强创建代理对象,编写一个回调拦截器:
/** * @author <a href="https://www.cnblogs.com/redwinter/">redwinter</a> * @since 1.0 **/ public class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("方法执行前:"+method); Object o1 = methodProxy.invokeSuper(o, objects); System.out.println("方法执行后:"+method); return o1; } }
xml配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="myBeforeInstantiation" class="com.redwinter.test.beforeInstantiation.MyBeforeInstantiation"/> <bean id="myInstantiationAwareBeanPostProcessor" class="com.redwinter.test.beforeInstantiation.MyInstantiationAwareBeanPostProcessor"/> </beans>
测试类:
/** * @author <a href="https://www.cnblogs.com/redwinter/">redwinter</a> * @since 1.0 **/ public class BeforeInstantiationTest { @Test public void test(){ ApplicationContext ac = new ClassPathXmlApplicationContext("before-instantiation.xml"); MyBeforeInstantiation bean = ac.getBean(MyBeforeInstantiation.class); bean.beforeInvoke(); } }
输出:
beanName: myBeforeInstantiation执行了 postProcessBeforeInstantiation 方法 方法执行前:public java.lang.String java.lang.Object.toString() 方法执行前:public native int java.lang.Object.hashCode() 方法执行后:public native int java.lang.Object.hashCode() 方法执行后:public java.lang.String java.lang.Object.toString() 创建对象:com.redwinter.test.beforeInstantiation.MyBeforeInstantiation$$EnhancerByCGLIB$$f92db8b4@1fd3711 beanName: myBeforeInstantiation执行了 postProcessAfterInitialization 方法 方法执行前:public void com.redwinter.test.beforeInstantiation.MyBeforeInstantiation.beforeInvoke() 提前实例化,开始执行业务.... 方法执行后:public void com.redwinter.test.beforeInstantiation.MyBeforeInstantiation.beforeInvoke()
可以看到,这里只执行了两个方法,一个是
postProcessBeforeInstantiation,是
InstantiationAwareBeanPostProcessor的前置实例化接口,一个是
postProcessAfterInitialization,是
BeanPostProcessor的后置实例化接口。
相当于说Bean
对象提前被创建了,而没有执行下面的doCreateBean
方法的逻辑。
Spring设计了很多的扩展点,帮助用户实现很多自定义的处理,
Spring强大之处就在这里。
这篇就介绍到这里,下一篇介绍
Spring其他方式的进行提前创建
Bean对象。
相关文章推荐
- 2、Spring的LocalSessionFactoryBean创建过程源码分析
- spring源码bean的创建过程-解决循环依赖-
- Spring 创建Bean的过程及其源码浅析
- Spring IOC 容器源码分析 - 创建单例 bean 的过程
- Spring 源码(13)Spring Bean 的创建过程(4)
- Spring IOC 容器源码分析 - 创建单例 bean 的过程
- 分析spring源码第五(三)篇:Spring中Bean的解析、加载、创建 过程总结
- Spring 源码 之 配置文件中的Bean在Spring中的创建过程
- 白话Spring源码(五):Bean的创建过程
- spring IOC源码分析(一)bean工厂的创建加载过程
- spring源码分析之bean的实例化过程
- Spring源码解析之bean的创建和销毁
- 看看Spring的源码(一)——Bean加载过程
- Spring 源码分析《Bean的获取与创建流程》
- 看看Spring的源码(一)——Bean加载过程
- Spring AOP高级——源码实现(3)AopProxy代理对象之JDK动态代理的创建过程
- Spring 3.2 源码解析 -- XML bean 元素到 BeanDefinition 解析过程
- spring源码学习 - 注解bean的初始化过程
- spring 加载bean过程源码简易解剖
- Spring创建Bean的过程