Bean 的生命周期 之 后处理Bean
这里先把Bean 的生命周期总结一下,然后引出后处理Bean
首先,Bean 的生命周期总共有11步:
1.instantiate bean对象实例化
2.populate properties 封装属性
3.如果Bean实现BeanNameAware 执行 setBeanName
4.如果Bean实现BeanFactoryAware 或者 ApplicationContextAware 设置工厂 setBeanFactory 或者上下文对象 setApplicationContext
5.如果存在类实现 BeanPostProcessor(后处理Bean) ,执行postProcessBeforeInitialization
6.如果Bean实现InitializingBean 执行 afterPropertiesSet
7.调用<bean init-method="init"> 指定初始化方法 init
8.如果存在类实现 BeanPostProcessor(处理Bean) ,执行postProcessAfterInitialization
9.执行业务处理
10.如果Bean实现 DisposableBean 执行 destroy
11.调用<bean destroy-method="customerDestroy"> 指定销毁方法 customerDestroy
通过测试的话,我们能很容易的验证这11个步骤,但是这11个步骤里面最重要的还是第5步和第8步
然而,第五步是在Bean初始化之前执行,我不知道这一步有什么用(请大神指点)
但是我知道,在第8步里面,可以添加一些自己的代码,就可以实现对方法的增强!也就是我们执行业务(第九步)之前就可以调用。然后对指定的方法进行增强
大家一定要注意,第五步和第八步室友前提的存在类实现 BeanPostProcessor 这里用户色标出希望大家注意!!!!!!!
也就是我们自己要定义一个后处理器,并实现其中的两个方法!如下代码:
1 public class MyBeanPostProcessor implements BeanPostProcessor{ 2 /** 3 * bean:实例对象 4 * beanName:在配置文件中配置的类的标识. 5 */ 6 public Object postProcessBeforeInitialization(Object bean, String beanName) 7 throws BeansException { 8 System.out.println("第五步:初始化之前执行..."); 9 return bean; 10 } 11 12 public Object postProcessAfterInitialization(final Object bean, String beanName) 13 throws BeansException { 14 System.out.println("第八步:初始化后执行..."); 15 } 16 }
这就是一个后处理器!没初始化一个Bean,都会调用第五步和第八步,所以,通过这一点,我们就可以增强自己的代码!
在第八步里面(postProcessAfterInitialization()),我们就可以编写自己的增强。
但是,这里注意一点就是:我们定义的这个后处理器,也是需要在配置文件中添加的。Spring在初始化bean过程中如果发现bean实现了BeanPostProcessor 接口,将会将其注册为bean后处理器,它对spring容器下的所有bean起作用,任何bean在 初始化过程都会通过bean后处理器做额外增强操作。
如下是测试类的代码:
public void demo1() { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext( "applicationContext.xml"); CustomerService customerService = (CustomerService) applicationContext.getBean("customerService"); customerService.add(); customerService.find(); applicationContext.close(); }
但是我们不想让所有的Bean 都被增强,这时候就可以使用动态代理来解决这个问题,可以做到只对某个方法进行增强。
代码如下:
1 public Object postProcessAfterInitialization(final Object bean, String beanName) 2 throws BeansException { 3 System.out.println("第八步:初始化后执行..."); 4 // 动态代理: 5 if(beanName.equals("customerService")){ 6 Object proxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces() , new InvocationHandler() { 7 // 调用目标方法的时候,调用invoke方法. 8 public Object invoke(Object proxy, Method method, Object[] args) 9 throws Throwable { 10 if("add".equals(method.getName())){ 11 System.out.println("权限校验..."); 12 Object result = method.invoke(bean, args); 13 System.out.println("权限校验后。。。"); 14 //System.out.println(System.currentTimeMillis()); 15 return result; 16 } 17 return method.invoke(bean, args); 18 } 19 }); 20 return proxy; 21 } 22 return bean; 23 }
这里用到了动态代理,只对customerService的add方法进行增强!!!
这里还要注意一点,我们这用的是JDK的动态代理,所以被代理的类必须实现某个接口才行!!!,所以,customerService是实现类接口的类!
而测试结果就很明显了:
在调用add方法之后,会自动调用代理方法中的两个输出语句!
其实后面学习的动态代理用到的就是后处理Bean的知识.