BeanPostProcessor

来源:互联网 发布:mac键盘大小写灯不亮 编辑:程序博客网 时间:2024/05/09 01:45

Spring提供了很多扩展接口,BeanPostProcessor接口和InstantiationAwareBeanPostProcessor接口就是其中两个。

 (实现对于所有Bean在初始化前后的自定义方法)

BeanPostProcessor

BeanPostProcessor接口作用是:如果我们需要在Spring容器完成Bean的实例化、配置和其他的初始化前后添加一些自己的逻辑处理,我们就可以定义一个或者多个BeanPostProcessor接口的实现,然后注册到容器中。

Spring中Bean的实例化过程图示:

由上图可以看到,Spring中的BeanPostProcessor在实例化过程处于的位置,BeanPostProcessor接口有两个方法需要实现:postProcessBeforeInitialization和postProcessAfterInitialization,

Java代码  收藏代码
  1. import org.springframework.beans.factory.config.BeanPostProcessor;  
  2.    
  3. public class MyBeanPostProcessor implements BeanPostProcessor {  
  4.    
  5.      public MyBeanPostProcessor() {  
  6.         super();  
  7.         System.out.println("这是BeanPostProcessor实现类构造器!!");          
  8.      }  
  9.    
  10.      @Override  
  11.      public Object postProcessAfterInitialization(Object bean, String arg1)  
  12.              throws BeansException {  
  13.          System.out.println("bean处理器:bean创建之后..");  
  14.          return bean;  
  15.      }  
  16.    
  17.      @Override  
  18.      public Object postProcessBeforeInitialization(Object bean, String arg1)  
  19.              throws BeansException {  
  20.          System.out.println("bean处理器:bean创建之前..");  
  21.        
  22.          return bean;  
  23.      }  
  24.  }  

 

BeanPostProcessor接口定义如下:

Java代码  收藏代码
  1. public interface BeanPostProcessor {  
  2.   
  3.     /** 
  4.      * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean 
  5.      * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} 
  6.      * or a custom init-method). The bean will already be populated with property values.    
  7.      */  
  8. //实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务  
  9.     Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;  
  10.   
  11.       
  12.     /** 
  13.      * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean 
  14.      * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}   
  15.      * or a custom init-method). The bean will already be populated with property values.       
  16.      */  
  17. //实例化、依赖注入、初始化完毕时执行  
  18.     Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;  
  19.   
  20. }  

 

 

由方法名字也可以看出,前者在实例化及依赖注入完成后、在任何初始化代码(比如配置文件中的init-method)调用之前调用;后者在初始化代码调用之后调用。

注意:

1、接口中的两个方法都要将传入的bean返回,而不能返回null,如果返回的是null那么我们通过getBean方法将得不到目标。

 

2、BeanFactory和ApplicationContext对待bean后置处理器稍有不同。ApplicationContext会自动检测在配置文件中实现了BeanPostProcessor接口的所有bean,并把它们注册为后置处理器,然后在容器创建bean的适当时候调用它,因此部署一个后置处理器同部署其他的bean并没有什么区别。而使用BeanFactory实现的时候,bean 后置处理器必须通过代码显式地去注册,在IoC容器继承体系中的ConfigurableBeanFactory接口中定义了注册方法:

 

Java代码  收藏代码
  1. /**  
  2.  * Add a new BeanPostProcessor that will get applied to beans created  
  3.  * by this factory. To be invoked during factory configuration.  
  4.  * <p>Note: Post-processors submitted here will be applied in the order of  
  5.  * registration; any ordering semantics expressed through implementing the  
  6.  * {@link org.springframework.core.Ordered} interface will be ignored. Note  
  7.  * that autodetected post-processors (e.g. as beans in an ApplicationContext)  
  8.  * will always be applied after programmatically registered ones.  
  9.  * @param beanPostProcessor the post-processor to register  
  10.  */    
  11. void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);   

 

 

另外,不要将BeanPostProcessor标记为延迟初始化。因为如果这样做,Spring容器将不会注册它们,自定义逻辑也就无法得到应用。假如你在<beans />元素的定义中使用了'default-lazy-init'属性,请确信你的各个BeanPostProcessor标记为'lazy-init="false"'。


=========================================================================================


 最近想对项目中的所有bean进行一个代理。然后监控bean得方法的使用情况。


        刚开始想的方法是:重写项目的beanFactory,然后再getBean的使用,对结果object进行一个代理,达到我的目的。但是发现重写getBean的方法,无法对bean中的依赖注入的bean(set进来的bean)进行代理。

       正好看到了beanPostProcessor的使用方法。可以在spring的xml的配置一个BeanPostProcessor,然后对所有的bean进行一个代理处理,正好可以满足我的需求!

BeanPostProcessor代码如下:
Java代码  收藏代码
  1. import java.lang.reflect.Proxy;  
  2. import java.util.Map;  
  3. import java.util.concurrent.ConcurrentHashMap;  
  4.   
  5. import org.springframework.beans.BeansException;  
  6. import org.springframework.beans.factory.config.BeanPostProcessor;  
  7.   
  8. import com.alibaba.common.logging.Logger;  
  9. import com.alibaba.common.logging.LoggerFactory;  
  10.   
  11. public class MyBeanPostProcesser implements BeanPostProcessor {  
  12.     private Map map = new ConcurrentHashMap(100);  
  13.     private static final Logger log = LoggerFactory.getLogger("myBeanPostProcesser");  
  14.   
  15.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
  16.         MyProxy proxy = new MyProxy();  
  17.   
  18.         if (beanName.contains("DB")) {  
  19.             return bean;  
  20.         }  
  21.   
  22.         if (bean.toString().contains("Proxy")) {  
  23.             log.info(beanName + "为代理类,不进行再次代理!");  
  24.             return bean;  
  25.         }  
  26.         if (beanName.contains("TransactionTemplate")) {  
  27.             log.info(beanName + "为TransactionTemplate类,不进行再次代理!该类为:" + bean);  
  28.             return bean;  
  29.         }  
  30.   
  31.         if (map.get(beanName) != null) {  
  32.             log.info(beanName + "已经代理过,不进行再次代理!");  
  33.             return map.get(beanName);  
  34.         }  
  35.         proxy.setObj(bean);  
  36.         proxy.setName(beanName);  
  37.         Class[] iterClass = bean.getClass().getInterfaces();  
  38.         if (iterClass.length > 0) {  
  39.             Object proxyO = Proxy.newProxyInstance(bean.getClass().getClassLoader(), iterClass, proxy);  
  40.             map.put(beanName, proxyO);  
  41.             return proxyO;  
  42.         } else {  
  43.             log.info(beanName + "么有接口不进行代理!");  
  44.             return bean;  
  45.         }  
  46.     }  
  47.   
  48.     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
  49.         return bean;  
  50.     }  
  51.   
  52. }  
 

代理类Proxy代码如下:
Java代码  收藏代码
  1. import java.lang.reflect.InvocationHandler;  
  2. import java.lang.reflect.Method;  
  3.   
  4. import com.alibaba.common.logging.Logger;  
  5. import com.alibaba.common.logging.LoggerFactory;  
  6.   
  7. import sun.reflect.Reflection;  
  8.   
  9. public class MyProxy implements InvocationHandler {  
  10.     private static final Logger log = LoggerFactory.getLogger("myself");  
  11.   
  12.     private Object obj;  
  13.   
  14.     private String name;  
  15.   
  16.     public String getName() {  
  17.         return name;  
  18.     }  
  19.   
  20.     public void setName(String name) {  
  21.         this.name = name;  
  22.     }  
  23.   
  24.     public Object getObj() {  
  25.         return obj;  
  26.     }  
  27.   
  28.     public void setObj(Object obj) {  
  29.         this.obj = obj;  
  30.     }  
  31.   
  32.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  33.         System.out.println("begin================" + "bean 名称为【" + name + "】方法为【" + method.getName() + "】========="  
  34.                 + obj.getClass());  
  35.         log.error("begin================" + "bean 名称为【" + name + "】方法为【" + method.getName() + "】========="  
  36.                 + obj.getClass());  
  37.         return method.invoke(obj, args);  
  38.     }  
  39.   
  40.     public void printDetail(String detail) {  
  41.         log.error(detail);  
  42.     }  
  43.   
  44. }  
 
感觉还是比较好使的!记录一下。以后再有监控的需求,可以考虑使用这种方式了!

转自:http://guoliangqi.iteye.com/blog/635826

0 0
原创粉丝点击