1、Bean后处理器(BeanPostProcessor)
Bean后处理器,负责对容器中所有的Bean进行某种特定的修改,从而使这批Bean全部获得某种新功能。
Object postProcessAfterInitialization(Object bean, String beanName):初始化之后执行。
这两个方法形参和返回值:
- bean:即将接受后处理的Bean
- beanName:即将接受被后处理的bean的id。
- 返回值:进行后处理后的Bean。程序既可对该Bean进行修改,也可以替换掉原来Bean、甚至返回null。步骤:
a.实现一个Bean处理器。实现BeanPostProcessor接口
b.将Bean后处理器配置在Spring容器中,Spring容器一旦检测到某个Bean实现了BeanPostProcessor接口,
Spring就会自动将该Bean注册成容器中的Bean后处理器。
bean的生命周期:
创建实例→注入依赖关系(setter)→BeanNameAware接口中的方法→ApplicationContextAware接口中的方法→初始化前的后处理
→调用afterPropertiesSet→调用init-method→初始化后的后处理→运行阶段→调用destroy→调用destory-method
(1)Bean后处理器使用
eg:
①MyBeanPostProcessor.java
public class MyBeanPostProcessor implements BeanPostProcessor{
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("-----初始化之后的后处理-----");
return bean;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("-----初始化之前的后处理-----");
if(bean.getClass() == User.class){
Field f;
try {
f = bean.getClass().getDeclaredField("name");
f.setAccessible(true);
f.set(bean,"自定义前缀 "+f.get(bean));
} catch (Exception e) {
e.printStackTrace();
}
}
return bean;
}
}
②beans.xml
<bean class="cony.domain.MyBeanPostProcessor"/>
<bean id="user" class="cony.domain.User"
p:name="小米"
p:age="4"
/>
<bean id="user2" class="cony.domain.User"
p:name="小明"
p:age="4"
/>
③测试:
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
User user = ctx.getBean("user",User.class);
User user2 = ctx.getBean("user2",User.class);
System.out.println(user);
System.out.println(user2);
测试结果:
问:Bean后处理器执行几次? 答:由执行结果看出有多少个Bean,它就会执行多少次。
2、容器后处理器(BeanFactoryPostProcessor)
负责对容器进行后处理,从而对Spring容器进行修改、增强。- postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory):参数代表了将要被后处理的容器。
只能修改Spring容器,不能替换,更不能将容器替换成null。步骤:
a.实现一个Bean处理器。实现BeanFactoryPostProcessor接口
b.将Bean后处理器配置在Spring容器中,Spring容器一旦检测到某个Bean实现了BeanFactoryPostProcessor接口,
Spring就会自动将该Bean注册成容器中的容器后处理器。
(1)容器后处理器使用
eg1:
①MyBeanFactoryPostProcessor.java
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor{
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
System.out.println("执行对容器的后处理");
}
}
②beans.xml
<bean class="cony.domain.MyBeanPostProcessor"/>
<bean class="cony.domain.MyBeanFactoryPostProcessor"/>
<bean id="user" class="cony.domain.User"
p:name="小米"
p:age="4"
/>
③测试
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
User user = ctx.getBean("user",User.class);
System.out.println(user);
测试结果:
(2)需要将配置文件中某些信息提取到专门的属性文件中配置管理(比如配置数据库),可以使用下面两个容器后处理器去加载属性文件。
i.PropertyPlaceholderConfigurer:1、先加载配置文件,2、再通过${key}来引用配置文件中的value。
ii.PropertyOverrideConfigurer: 直接在属性文件中配置即可。
eg2:
_平常获取数据库连接:
①beans.xml:
②测试:
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
DataSource source = ctx.getBean("dataSource",DataSource.class);
System.out.println(source.getConnection());
测试结果:
坏处:属性值改变时需要打开代码修改,所以一般放在属性文件中配置。
_使用PropertyPlaceholderConfigurer:
①properties文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/数据库名
user=用户名
password=密码
maxSize=200
minSize=2
initSize=2
②beans.xml
将属性文件放在类路径下,所以用classpath进行加载
其中加载配置文件的代码可以简化为如下:
注:需要导入命名空间
_使用PropertyOverrideConfigurer:
①beans.xml:
②properties文件:需要特定格式