博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《玩转Spring》第二章 BeanPostProcessor扩展
阅读量:5111 次
发布时间:2019-06-13

本文共 6567 字,大约阅读时间需要 21 分钟。

版权声明:本文为博主原创文章。未经博主同意不得转载。

https://blog.csdn.net/shan9liang/article/details/34421141

上一章。介绍了怎样。

这一章,我们介绍怎样通过实现BeanPostProcessor接口,对容器中的Bean做一层代理。来满足我们的个性化需求。

一、基本原理

我非常不想贴代码,显得太没水平。有时候自己的语言又非常空洞。不得不贴代码,感觉用代码来说明一件事反而更easy些。

import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;public class BeanPostPrcessorImpl implements BeanPostProcessor {     // Bean 实例化之前运行该方法    public Object postProcessBeforeInitialization(Object bean, String beanName)           throws BeansException {       System.out.println( beanName + "開始实例化");       return bean;    }     // Bean 实例化之后运行该方法    public Object postProcessAfterInitialization(Object bean, String beanName)           throws BeansException {       System.out.println( beanName + "实例化完毕");       return bean;    }}

然后将这个BeanPostProcessor接口的实现配置到Spring的配置文件里就能够了:

<bean class="com.jialin.spring.BeanPostPrcessorImpl"/>

注意:

1、BeanPostProcessor的作用域是容器级的,它仅仅和所在容器有关。

2、BeanFactory和ApplicationContext对待bean后置处理器稍有不同。ApplicationContext会自己主动检測在配置文件里实现了BeanPostProcessor接口的全部bean,并把它们注冊为后置处理器。然后在容器创建bean的适当时候调用它。部署一个后置处理器同部署其它的bean并没有什么差别。

而使用BeanFactory实现的时候。bean 后置处理器必须通过以下相似的代码显式地去注冊:

BeanPostPrcessorImpl beanPostProcessor = new BeanPostPrcessorImpl();Resource resource = new FileSystemResource("applicationContext.xml");ConfigurableBeanFactory factory = new XmlBeanFactory(resource);factory.addBeanPostProcessor(beanPostProcessor);factory.getBean("beanName");

二、应用

好东西总要用起来

1、利用BeanPostProcessor接口实现Bean的动态代理。

2、自己主动注入Logging。用于记录日志。

Logger注解

@Retention(RetentionPolicy.RUNTIME)@Target( {        ElementType.FIELD})public @interface Logger {}package com.jialin.framework.annotation;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanInitializationException;import org.springframework.beans.factory.config.BeanPostProcessor;import java.lang.reflect.Field;import java.util.ArrayList;import java.util.Collections;import java.util.List;public class LogBeanPostProcessor implements BeanPostProcessor {        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {            return bean;        }        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {            List
> clazzes = getAllClasses(bean); for (Class
clazz : clazzes) { initializeLog(bean, clazz); } return bean; } /** * 取得指定bean的class以及全部父类的列表, 该列表排列顺序为从父类到当前类 * @param bean * @return */ private List
> getAllClasses(Object bean) { Class

extends Object> clazz = bean.getClass(); List<Class<?

>> clazzes = new ArrayList<Class<?

>>(); while (clazz != null) { clazzes.add(clazz); clazz = clazz.getSuperclass(); } Collections.reverse(clazzes); return clazzes; } /** * 对logger变量进行初始化 * * @param bean * @param clazz */ private void initializeLog(Object bean, Class<? extends Object> clazz) { Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (field.getAnnotation(Logger.class) == null) { continue; } if (!field.getType().isAssignableFrom(Log.class)) { continue; } field.setAccessible(true); try { field.set(bean, LogFactory.getLog(clazz)); } catch (Exception e) { throw new BeanInitializationException(String .format("初始化logger失败!bean=%s;field=%s", bean, field)); } } } }

在Spring配置文件里。增加

     <!--配置依据注解,自己主动注入Log对象-->

    <bean id="logBeanPocessor" class="com.jialin.framework.annotation.LogBeanPostProcessor" lazy-init="false" />

//实现代理的BeanPostProcessor的实例。当中注入上文介绍的log: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 org.apache.commons.logging.Log; public class ProxyBeanPostProcesser implements BeanPostProcessor {    private Map map = new ConcurrentHashMap(100);   //使用logger的注解来简化定义,并自己主动注入    @Logger    private static final Log log;     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        MyProxy proxy = new MyProxy();         if (bean.toString().contains("Proxy")) {            log.info(beanName + "为代理类,不进行再次代理!");            return bean;        }        //……        //能够加一些其它条件。过滤掉你不想代理的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;    } } import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import org.apache.commons.logging.Log;import sun.reflect.Reflection; //代理类Proxy。当中注入上文介绍的log:public class MyProxy implements InvocationHandler {   //使用logger的注解来简化定义,并自己主动注入    @Logger      private static final Log  log;     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 {        log.info("-------------------" + "bean 名称为【" + name + "】方法为【" + method.getName() + "】-------------"                + obj.getClass());        return method.invoke(obj, args);    }     public void printDetail(String detail) {        log.error(detail);    } }

在Spring配置文件里。增加

<!--配置自己主动为Bean配置代理对象-->

<bean id="proxyBeanPocessor" class="com.jialin.framework.proxy. ProxyBeanPostProcesser " />

从上面的介绍不难看出,实现了BeanPostProcessor接口定制我们自己的Bean处理器能够在Spring容器初始化Bean的时候做我们想做的非常多事。

Spring首先会使用自己的处理器。然后陆续使用我们的处理器,典型的装饰者模式,我们自己定义的处理器就是一个个详细的装饰者。

在这里预告一下,兴许会出一个文章,教大家怎样《实现一个面向服务的IOC容器。不使用不论什么框架。纯j2se代码》

这篇到这,下篇继续,敬请关注!谢谢

贾琳   写于 2014-6-25 河北廊坊  多云

                            

转载于:https://www.cnblogs.com/ldxsuanfa/p/10727721.html

你可能感兴趣的文章
微信小程序-发起 HTTPS 请求
查看>>
WPF动画设置1(转)
查看>>
基于node/mongo的App Docker化测试环境搭建
查看>>
秒杀9种排序算法(JavaScript版)
查看>>
struts.convention.classes.reload配置为true,tomcat启动报错
查看>>
MySQL的并行复制多线程复制MTS(Multi-Threaded Slaves)
查看>>
好玩的-记最近玩的几个经典ipad ios游戏
查看>>
PyQt5--EventSender
查看>>
Sql Server 中由数字转换为指定长度的字符串
查看>>
Java 多态 虚方法
查看>>
Unity之fragment shader中如何获得视口空间中的坐标
查看>>
万能的SQLHelper帮助类
查看>>
tmux的简单快捷键
查看>>
[Swift]LeetCode922.按奇偶排序数组 II | Sort Array By Parity II
查看>>
Html5 离线页面缓存
查看>>
《绿色·精简·性感·迷你版》易语言,小到不可想象
查看>>
Android打包key密码丢失找回
查看>>
VC6.0调试技巧(一)(转)
查看>>
类库与框架,强类型与弱类型的闲聊
查看>>
webView添加头视图
查看>>