Spring提供了很多切面,用于在项目启动的不同阶段植入代码。

BeanPostProcessor :可以在Bean创建之后,在初始化之前、初始化之后,进行一些额外的操作。

InitializingBean:在所有的Bean互相注入和Properties参数设置之后,在初始化函数调用之前,进行一些额外的操作。

BeanFactoryPostProcessor :在所有的Bean初始化之前,进行一些额外的操作,例如:手动注册对象到Spring容器。

具有相似功能的切面还有:

ContextLoaderListener:因为本身就是侦听项目启动和关闭的,直接在启动函数中添加后置代码也可以。

Bean的后处理

public class Person implements InitializingBean{
private String name; public Person() {
System.out.println("创建Person实例");
} public void setName(String name) {
System.out.println("Set方式设值:"+name);
this.name = name;
} public void init(){
System.out.println("Person初始化:init执行");
} @Override
public String toString() {
return "Person [name=" + name + "]";
} @Override
public void afterPropertiesSet() throws Exception {
System.out.println("在Bean后处理之后:afterPropertiesSet执行");
}
}
/**
* Bean后处理器
* @author ChenSS
* @2016年12月30日
*/
public class MyBeanPostProcessor implements BeanPostProcessor { @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean后处理postProcessBeforeInitialization之后:init之前");
return bean;
} @Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean后处理postProcessAfterInitialization:init之后");
if (!(bean instanceof Person))
return bean;
Person person = (Person) bean;
person.setName("新名字:xiaohua");
return person;
}
}
<?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-3.0.xsd">
<bean id="xiaoming" class="com.spring.test.Person" init-method="init">
<property name="name" value="小明" />
</bean>
<!-- 后处理器 -->
<bean id="myBeanPostProcessor" class="com.spring.test.MyBeanPostProcessor" />
</beans>
public class Test {
public static void main(String[] args) {
new ClassPathXmlApplicationContext("applicationContext.xml");
}
}

容器后处理器

容器后处理器,是一个大的切面,在每一个Bean创建之后,但是在初始化之前;

注意:Spring中XML解析是顺序执行的,如果提前注册了容器后处理器,后处理器对后续Bean无效(不严谨的说法,未做全面测试,但是确实反生过此Bug)。

定义一个最简单的容器后处理器

/**
* 容器后处理器,实现BeanFactoryPostProcessor接口
* @author ChenSS
* @2016年12月30日
*/
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("容器后处理器:postProcessBeanFactory");
System.out.println(beanFactory.getClass().getName());
}
}

<?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-3.0.xsd">
<bean id="xiaoming" class="com.spring.test.ioc.Person" init-method="init">
<property name="name" value="小明" />
</bean>
<!-- 后处理器 -->
<bean class="com.spring.test.ioc.MyBeanFactoryPostProcessor" />
</beans>

代码本身没什么意义,只是打印一下日志,让大家看一下效果,可见容器的后处理器,是在所有Bean创建之后,但是在初始化之前执行的。

附:PropertyPlaceholderConfigurer读取dp.properties配置文件

<?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-3.0.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>db.properties</value>
<!-- <value>other value...</value> -->
</list>
</property>
</bean>
<bean id="dataSource" class="com.spring.test.ioc.DateBaseProperties">
<!-- 以下这些值均来自配置文件dp.properties -->
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean>
</beans>

准备dp.properties文件,这个文件也是放在Src根目录下

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testdb
jdbc.user=root
jdbc.password=123456

对应的测试用JavaBean。

public class DateBaseProperties {
private String driverClass;
private String jdbcUrl;
private String user;
private String password; //set、toString方法省略
}

PropertyOverrideConfigurer读取dp.properties配置文件

看着前面的配置文件,总觉得怪怪的,不是在dp.properties配置了一次嘛?为什么还要在XML再配置一次?

Spring框架自带的加载工具类PropertyOverrideConfigurer可以帮我们解决这个问题。

<?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-3.0.xsd">
<bean class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
<property name="locations">
<list>
<value>db.properties</value>
<!-- <value>other value...</value> -->
</list>
</property>
</bean>
<!-- 这里的代码全删了 -->
<bean id="dataSource" class="com.spring.test.ioc.DateBaseProperties"/>
</beans>

不过关于db.properties的配置得调整一下,把前面的jdbc改成dataSource,名字和Bean的id对应。

dataSource.driverClass=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql://localhost:3306/testdb
dataSource.user=root
dataSource.password=123456

上面两个容器后处理器的测试结果如下

下面例举了一些我看到的、查到的其他后处理器:

CustomAutowireConfigurer自定义自动装配的配置器
CustomScopeConfigurer自定义作用于的配置器
CustomEditorConfigurer:此类注册一个PropertyEditor实现,该实现用户将配置文件中的字符串值转换为bean需要的类型。
ServletContextPropertyPlaceholderConfigurer:此回调处理器泛化了PropertyPlaceholderConfigurer类。因此,只要bean属性遵照指定命名规范,他就替换bean的属性。除了他的超类,此处理器还将从处理应用程序的servlet上下文参数入口装载值。
PreferencesPlaceholderConfigurer:此回调处理器将JDK1.4Preperences API替换bean属性中的值,此Preperences API标识他将解析来自用户Preperences的值,然后系统Preperences获得值,最后从一个引用文件获得值。

afterPropertiesSet

Spring框架——后处理器的更多相关文章

  1. Spring的后处理器-BeanPostProcessor跟BeanFactoryPostProcessors

    最近在重读spring源码(为什么要重读?因为不得不承认,去年跟着<深入解析sping源码>一书过了一遍spring的源码,除了满脑袋都是各种BeanFactory跟BeanDefinit ...

  2. Spring Bean后处理器以及容器后处理器【转】

    Bean后处理器:即当spring容器实例化Bean实例之后进行的增强处理. 容器后处理器:对容器本身进行处理,并总是在容器实例化其他任何Bean之前读取配置文件的元数据并可能修改这些数据. 一.Be ...

  3. Spring.net 后处理器 可用来切换实例

    .xml配置 <!--我们在Object.xml文件上将HexuObjectPostProcessor注册到上下文对象中去--> <object id="hexu" ...

  4. Spring框架简单介绍

    原文地址:  http://my.oschina.net/myriads/blog/37922 1.使用框架的意义与Spring的主要内容 随着软件结构的日益庞大,软件模块化趋势出现,软件开发也须要多 ...

  5. JavaWeb_(Spring框架)在Struts+Hibernate框架中引入Spring框架

    spring的功能:简单来说就是帮我们new对象,什么时候new对象好,什么时候销毁对象. 在MySQL中添加spring数据库,添加user表,并添加一条用户数据 使用struts + hibern ...

  6. 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring DI(依赖注入)的实现方式属性注入和构造注入

    依赖注入(Dependency Injection,DI)和控制反转含义相同,它们是从两个角度描述的同一个概念. 当某个 Java 实例需要另一个 Java 实例时,传统的方法是由调用者创建被调用者的 ...

  7. 8 -- 深入使用Spring -- 1...两种后处理器

    8.1 两种后处理器 Spring框架提供了很好的扩展性,出了可以与各种第三方框架良好整合外,其IoC容器也允许开发者进行扩展,这种扩展甚至无须实现BeanFactor或ApplicationCont ...

  8. XI.spring的点点滴滴--IObjectFactoryPostProcessor(工厂后处理器)

    承接上文 IObjectFactoryPostProcessor(工厂后处理器)) 前提是实现接口的对象注册给当前容器 直接继承的对象调用这个postProcessBeanFactory方法,参数为工 ...

  9. Ⅹ.spring的点点滴滴--IObjectPostProcessor(对象后处理器)

    承接上文 IObjectPostProcessor(对象后处理器) 前提是实现接口的对象注册给当前容器 C#: 通过继承AbstractObjectFactory对象的AddObjectPostPro ...

随机推荐

  1. [js高手之路] 设计模式系列课程 - jQuery的extend插件机制

    这里在之前的文章[js高手之路] 设计模式系列课程 - jQuery的链式调用与灵活的构造函数基础上增加一个extend浅拷贝,可以为对象方便的扩展属性和方法, jquery的插件扩展机制,大致就是这 ...

  2. Java这些冷知识你知道吗?

    1)jvm有很多种,其实jvm是一个标准,sun做的那个叫hotspot,作者就是后来v8的作者lars bak,其他公司也做过jvm,其中做得比较好的有bea的jrockit,其他的包括ibm的r9 ...

  3. 为什么String类是不可变的?

    为什么String类是不可变的? String类 什么是不可变对象 当满足以下条件时,对象才是不可变的: 对象创建以后其状态就不能修改. 对象的所有域都是final类型的. 对象是正确创建的(在对象的 ...

  4. C#连接oracle数据库提示ORA-12154: TNS: 无法解析指定的连接标识符

    C#连接oracle数据库提示ORA-12154: TNS: 无法解析指定的连接标识符如果PLSQL Develope能连接上而用代码无法连接上则可以考虑sqlnet.ora文件中是否有NAMES.D ...

  5. MySQL分区表与合并表

    一.分区表 1. 什么是分区表? 对用户来说,分区表是一个独立的逻辑表,但是底层由多个物理子表组成(所以索引也是按照分区的子表定义的, 而没有全局索引).实现分区的代码实际上是对一组底层表的句柄对象的 ...

  6. LeetCode 594. Longest Harmonious Subsequence (最长的协调子序列)

    We define a harmonious array is an array where the difference between its maximum value and its mini ...

  7. 初识.Net IL

    1.IL基本资料 1.IL概述 IL是.NET框架中中间语言(Intermediate Language)的缩写.使用.NET框架提供的编译器可以直接将源程序编译为.exe或.dll文件,但此时编译出 ...

  8. 67、django之模型层(model)--查询补充及mookie

    本篇导航: F查询与Q查询 cookie 一.F查询与Q查询 1.以Book表为例 class Book(models.Model) : title = models.CharField(max_le ...

  9. JMeter 压力测试使用CSV参数

    表示之前从没用过JMeter所以记录一下使用过程 Apache JMeter是Apache组织开发的基于Java的压力测试工具.用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测 ...

  10. print、println与printf之间的区别

    //print没有换行的而println有自动换行功能.实例:uprint.java class uprint{public static void main(String arg[]){int i, ...