spring提供了两种后置处理bean的扩展接口, 分别为BeanPostProcessor和BeanFactoryPostProcessor,
BeanPostProcessor
BeanPostProcessor是针对bean的处理,
BeanPostProcessor
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
BeanPostProcessor提供了两个方法,分别在初始化方法之前和之后执行, 这里的初始化方法就是bean的init-method。
如果我们定义了一个BeanPostProcessor的实现类,默认会对spring ioc容器中的所有bean进行处理, 如果要对某个具体的bean进行处理, 可以通过方法的参数(Object bean, String beanName)来区分,Object bean是bean的实例,String beanName是我们bean定义的id或name属性值。
实例
MyBeanPostProcessor
package com.duohoob.spring.processor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("testService".equals(beanName)) {
System.out.println("init-method之前");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("testService".equals(beanName)) {
System.out.println("init-method之后");
}
return bean;
}
}
application-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"
default-lazy-init="false">
<context:component-scan base-package="com.example.duohoob"/>
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="testService" class="com.example.duohoob.service.TestServiceImpl" init-method="init">
<property name="dataSource" ref="druidDataSource"/>
</bean>
</beans>
TestServiceImpl
package com.example.duohoob.service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;
import com.alibaba.druid.pool.DruidDataSource;
@Component("testService")
public class TestServiceImpl implements TestService {
private DruidDataSource dataSource;
public void setDataSource(DruidDataSource dataSource) {
this.dataSource = dataSource;
}
@PostConstruct
public void init() {
System.out.println("创建bean");
}
@PreDestroy
public void destroy() {
System.out.println("销毁bean");
}
@Override
public String test() {
System.out.println(dataSource);
return "success";
}
}
测试
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application-context.xml");
Object bean = context.getBean("testService");
System.out.println(bean);
((AbstractApplicationContext) context).close();
}
BeanFactoryPostProcessor
BeanFactoryPostProcessor是BeanFactory级别的处理, 在工厂产生之后、对象创建之前执行,
它只有一个方法,
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
参数为ConfigurableListableBeanFactory,该类型定义了一些方法, 其中有个getBeanDefinition可以获取我们的beandefinition,然后可以对属性进行修改,
应用案例:PlaceholderConfigurerSupport,
它的作用就是读取外部的配置,
<context:property-placeholder location="classpath:jdbc.properties"/>
然后替换配置中的占位符,
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
|