Spring 基础教程 (第 10 章) - Spring Bean 后置处理器

第 10 章 Spring Bean 后置处理器

本章节主要介绍在《Spring 基础教程 (第 9 章) - Spring Bean 生命周期(1)》一章提到的 BeanPostProcessor 接口。 BeanPostProcessor 接口也被称为后置处理器,通过该接口可以自定义调用初始化前后执行的操作方法。

10. 1. BeanPostProcessor 接口

BeanPostProcessor 接口源码如下:

public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

该接口中包含了两个方法:

  • postProcessBeforeInitialization() 方法:在 Bean 实例化、属性注入后,初始化前调用。
  • postProcessAfterInitialization() 方法:在 Bean 实例化、属性注入、初始化都完成后调用。

当需要添加多个后置处理器实现类时,默认情况下 Spring 容器会根据后置处理器的定义顺序来依次调用。也可以通过实现 Ordered 接口的 getOrder 方法指定后置处理器的执行顺序。该方法返回值为整数,默认值为 0,取值越大优先级越低。

例 1

下面我们就来演示下 BeanPostProcessor 接口的用法,步骤如下:

创建命名为 Woman 的类,代码如下:

package section10.demo1;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * ClassName: Woman
 * Description: TODO
 *
 * @author chuanlu
 * @version 1.0.0
 */
public class Woman {
    private static final Log LOGGER = LogFactory.getLog(Woman.class);
    // 姓名
    private String name;
    // 年龄
    private Integer age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public void init() {
        LOGGER.info("Bean 正在初始化,开始梳妆打扮换衣服");
    }

    public void destroy() {
        LOGGER.info("Bean 正在销毁,关灯睡觉");
    }

    @Override
    public String toString() {
        return "Woman{" +
                "name='" + name + '\'' +
                "age='" + age + '\'' +
                '}';
    }
}

创建命名为 MakeUp 的类,代码如下:

package section10.demo1;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;

/**
 * ClassName: MakeUp
 * Description: TODO
 *
 * @author chuanlu
 * @version 1.0.0
 */
public class MakeUp implements BeanPostProcessor, Ordered {
    private static final Log LOGGER = LogFactory.getLog(MakeUp.class);

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        LOGGER.info("准备化妆品 : " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        LOGGER.info("卸妆 : " + beanName);
        return bean;
    }

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

注意:postProcessBeforeInitialization()postProcessAfterInitialization() 方法返回值不能为 null,否则会报空指针异常或者通过 getBean() 方法获取不到 Bean 实例对象。

创建命名为 DressUp 的类,代码如下:

package section10.demo1;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;

/**
 * ClassName: DressUp
 * Description: TODO
 *
 * @author chuanlu
 * @version 1.0.0
 */
public class DressUp implements BeanPostProcessor, Ordered {
    private static final Log LOGGER = LogFactory.getLog(DressUp.class);

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        LOGGER.info("准备约会服装 : " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        LOGGER.info("换睡衣 : " + beanName);
        return bean;
    }

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

修改 Spring 配置文件 spring-config.xml,配置如下:

<?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="woman" class="section10.demo1.Woman" init-method="init" destroy-method="destroy">
        <property name="name" value="小丽"/>
        <property name="age" value="24"/>
    </bean>

    <!-- 注册处理器 -->
    <bean class="section10.demo1.MakeUp"/>
    <bean class="section10.demo1.DressUp"/>

</beans>

创建命名为 MainApp 的类,代码如下:

package section10.demo1;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * ClassName: MainApp
 * Description: TODO
 *
 * @author chuanlu
 * @version 1.0.0
 */
public class MainApp {
    private static final Log LOGGER = LogFactory.getLog(MainApp.class);

    public static void main(String[] args) {
        // 获取 ApplicationContext 容器
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        // 获取名为 woman 的 Bean
        Woman woman = context.getBean("woman", Woman.class);
        // 日志输出对象信息
        LOGGER.info(woman.toString());
        //手动销毁 Bean
        context.close();
    }
}

执行 MainApp 中的 main 方法,控制台输出如下:

4月 08, 2022 7:23:57 下午 section10.demo1.MakeUp postProcessBeforeInitialization
信息: 准备化妆品 : woman
4月 08, 2022 7:23:57 下午 section10.demo1.DressUp postProcessBeforeInitialization
信息: 准备约会服装 : woman
4月 08, 2022 7:23:57 下午 section10.demo1.Woman init
信息: Bean 正在初始化,开始梳妆打扮换衣服
4月 08, 2022 7:23:57 下午 section10.demo1.MakeUp postProcessAfterInitialization
信息: 卸妆 : woman
4月 08, 2022 7:23:57 下午 section10.demo1.DressUp postProcessAfterInitialization
信息: 换睡衣 : woman
4月 08, 2022 7:23:57 下午 section10.demo1.MainApp main
信息: Woman{name='小丽'age='24'}
4月 08, 2022 7:23:57 下午 section10.demo1.Woman destroy
信息: Bean 正在销毁,关灯睡觉

由运行结果可以看出,postProcessBeforeInitialization() 方法是在 Bean 实例化和属性注入后,自定义初始化方法前执行的。而 postProcessAfterInitialization() 方法是在自定义初始化方法后执行的。由于 getOrder 方法返回值越大,优先级越低,因此 MakeUp(化妆) 先执行,DressUp(打扮) 后执行。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

传陆编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值