【TcaplusDB知识库】TcaplusDB Tca
284 2023-04-03 05:02:00
继续上一篇Spring Bean
的创建过程的解读,上一篇介绍了Spring
在创建过程中doGetBean
方法,在执行过程中会调用getSingleton
方法并且设置一个lambda
表达式,这个lambda
表达式是ObjectFactory
的实现,当调用这个接口的getObject
方法时就会执行到createBean
方法,在createBean
方法中会进行bean
类型的解析,并且会进行方法覆盖的设置,当我们配置了如:lookup-method
或者replace-method
方法的时候就会在创建Bean
的过程中设置一个CGLIB
的工厂类为Bean
的对象,当调用的时候就会触发CGLIB
的拦截器方法执行具体的Bean
的获取,如果是单例对象引用了多例对象,那么就会每次创建一个新的对象给调用的方法执行。
接下来继续解读Spring
创建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);}
接下来试试提前实例化的案例:
创建一个需要提前实例化的对象:
/** * @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 {@Overridepublic 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;}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {System.out.println("beanName: " + beanName + "执行了 postProcessAfterInstantiation 方法");return false;}@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {System.out.println("beanName: " + beanName + "执行了 postProcessProperties 方法");return pvs;}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("beanName: " + beanName + "执行了 postProcessBeforeInitialization 方法");return bean;}@Overridepublic 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@1fd3711beanName: 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
对象。