最近想對項目中的所有bean進行一個代理。然后監控bean得方法的使用情況。
剛開始想的方法是:重寫項目的beanFactory,然后再getBean的使用,對結果object進行一個代理,達到我的目的。但是發現重寫getBean的方法,無法對bean中的依賴注入的bean(set進來的bean)進行代理。
正好看到了beanPostProcessor的使用方法。可以在spring的xml的配置一個BeanPostProcessor,然后對所有的bean進行一個代理處理,正好可以滿足我的需求!
BeanPostProcessor代碼如下:
- import java.lang.reflect.Proxy;
- import java.util.Map;
- import java.util.concurrent.ConcurrentHashMap;
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.BeanPostProcessor;
- import com.alibaba.common.logging.Logger;
- import com.alibaba.common.logging.LoggerFactory;
- public class MyBeanPostProcesser implements BeanPostProcessor {
- private Map map = new ConcurrentHashMap(100);
- private static final Logger log = LoggerFactory.getLogger("myBeanPostProcesser");
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- MyProxy proxy = new MyProxy();
- if (beanName.contains("DB")) {
- return bean;
- }
- if (bean.toString().contains("Proxy")) {
- log.info(beanName + "為代理類,不進行再次代理!");
- return bean;
- }
- if (beanName.contains("TransactionTemplate")) {
- log.info(beanName + "為TransactionTemplate類,不進行再次代理!該類為:" + bean);
- return bean;
- }
- if (map.get(beanName) != null) {
- log.info(beanName + "已經代理過,不進行再次代理!");
- return map.get(beanName);
- }
- proxy.setObj(bean);
- proxy.setName(beanName);
- Class[] iterClass = bean.getClass().getInterfaces();
- if (iterClass.length > 0) {
- Object proxyO = Proxy.newProxyInstance(bean.getClass().getClassLoader(), iterClass, proxy);
- map.put(beanName, proxyO);
- return proxyO;
- } else {
- log.info(beanName + "么有接口不進行代理!");
- return bean;
- }
- }
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- return bean;
- }
- }
代理類Proxy代碼如下:
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import com.alibaba.common.logging.Logger;
- import com.alibaba.common.logging.LoggerFactory;
- import sun.reflect.Reflection;
- public class MyProxy implements InvocationHandler {
- private static final Logger log = LoggerFactory.getLogger("myself");
- private Object obj;
- private String name;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Object getObj() {
- return obj;
- }
- public void setObj(Object obj) {
- this.obj = obj;
- }
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- System.out.println("begin================" + "bean 名稱為【" + name + "】方法為【" + method.getName() + "】========="
- + obj.getClass());
- log.error("begin================" + "bean 名稱為【" + name + "】方法為【" + method.getName() + "】========="
- + obj.getClass());
- return method.invoke(obj, args);
- }
- public void printDetail(String detail) {
- log.error(detail);
- }
- }
感覺還是比較好使的!記錄一下。以后再有監控的需求,可以考慮使用這種方式了!