Spring Bean 后置处理器BeanPostProcessor

Spring Bean 后置处理器BeanPostProcessor

Spring 提供一种机制,只要实现此接口BeanPostProcessor,并将实现类提供给spring容器,spring容器将自动执行,在初始化方法前执行before(),在初始化方法后执行after()

可以配置多个 BeanPostProcessor 接口,通过设置 BeanPostProcessor 实现的 Ordered 接口提供的 order 属性来控制这些 BeanPostProcessor 接口的执行顺序。

ApplicationContext 会自动检测由 BeanPostProcessor 接口的实现定义的 bean,注册这些 bean 为后置处理器,然后通过在容器中创建 bean,在适当的时候调用它。

在这里插入图片描述

  • Factory hook(勾子) that allows for custom modification of new bean instances, e.g. checking for marker interfaces or wrapping them with proxies.

  • spring提供工厂勾子,用于修改实例对象,可以生成代理对象,是AOP底层。

    模拟
    A a =new A();
    a = B.before(a) --> 将a的实例对象传递给后处理bean,可以生成代理对象并返回。
    a.init();
    a = B.after(a);
    a.addUser(); //生成代理对象,目的在目标方法前后执行(例如:开启事务、提交事务)
    a.destroy()

BeanPostProcessor实现类代码演示

  • BeanPostProcessor实现类1,同时实现getOrder方法来控制这些 执行顺序
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;

public class PostProcessor implements BeanPostProcessor,Ordered {

    //可以在初始化 bean 的之前和之后实现更复杂的逻辑。
    //在Init-method的前后执行
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization1:" + beanName);
        ((InitHelloWorld)bean).getMessage();
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization1:" + beanName);
        ((InitHelloWorld)bean).getMessage();
        return bean;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
  • BeanPostProcessor实现类2
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;

public class PostProcessor2 implements BeanPostProcessor,Ordered {

    //可以在初始化 bean 的之前和之后实现更复杂的逻辑。
    //在Init-method的前后执行
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization2:" + beanName);
        ((InitHelloWorld)bean).getMessage();
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization2:" + beanName);
        ((InitHelloWorld)bean).getMessage();
        return bean;
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

  • 配置
<?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.xsd">


    <bean id="initHelloWorld" class="com.cc.study.lifecycle.InitHelloWorld"
          init-method="init" destroy-method="destroy">
        <property name="message" value="Hello World!"></property>
    </bean>

    <bean id="postProcessor" class="com.cc.study.lifecycle.PostProcessor"></bean>
    <bean id="postProcessor2" class="com.cc.study.lifecycle.PostProcessor2"></bean>
</beans>

  • InitHelloWorld
public class InitHelloWorld{
    private String message;

    public void setMessage(String message){
        this.message  = message;
    }
    public void getMessage(){
        System.out.println("Your Message : " + message);
    }
    public void init(){
        System.out.println("Bean is going through init.");
    }
    public void destroy(){
        System.out.println("Bean will destroy now.");
    }
}

  • 测试
    @Test
    public void demo(){
        String xmlPath = "lifecycle2.xml";
        AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
        InitHelloWorld initHelloWorld = applicationContext.getBean("initHelloWorld",InitHelloWorld.class);
        initHelloWorld.getMessage();
        applicationContext.registerShutdownHook();
    }

在这里插入图片描述

BeanPostProcessor生成代理对象

  • MyBeanPostProcessor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MyBeanPostProcessor implements BeanPostProcessor {

	@Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("前方法 : " + beanName);
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
		System.out.println("后方法 : " + beanName);
		// bean 目标对象
		// 生成 jdk 代理
		return Proxy.newProxyInstance(
					MyBeanPostProcessor.class.getClassLoader(), 
					bean.getClass().getInterfaces(), 
					new InvocationHandler(){
						@Override
						public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
							System.out.println("------开启事务");
							System.out.println("调用方法:" + method.getName());
							//执行目标方法
							Object obj = method.invoke(bean, args);
							
							System.out.println("------提交事务");
							return obj;
						}});
	}
}

  • 配置
<?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.xsd">

    <!-- 创建dao实例 -->
    <bean id="bookDaoId" class="com.cc.study.di.BookDaoImpl"></bean>
    <!-- 将后处理的实现类注册给spring -->
    <bean id="myBeanPostProcessor" class="com.cc.study.lifecycle.MyBeanPostProcessor"></bean>

</beans>

  • BookDaoImpl
public class BookDaoImpl implements BookDao {

	@Override
	public void addBook() {
		System.out.println("di add book");
	}

}

  • 测试
    @Test
    public void demo(){
        String xmlPath = "lifecycle3.xml";
        AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
        BookDao bookDao = applicationContext.getBean("bookDaoId",BookDao.class);
        bookDao.addBook();
    }

在这里插入图片描述

注意:
问题1:后处理bean作用某一个目标类,还是所有目标类?
所有
问题2:如何只作用一个?
通过“参数2”beanName进行控制

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值