BeanFactoryPostProcessor —— bean工厂后置处理器

BeanFactoryPostProcessor是Spring容器初始化过程中使用到的一个关键的接口类,翻译过来就是bean工厂后置处理器。BeanFactoryPostProcessor可以在Spring容器实例化bean之前读取bean的定义(BeanDefinition),并可以修改它。下面使用代码示范BeanFactoryPostProcessor的使用


项目pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zaomianbao</groupId>
    <artifactId>spring</artifactId>
    <version>1.0.0</version>

    <dependencies>

        <!-- spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.11.RELEASE</version>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
        </dependency>

        <!-- logback -->
        <dependency>
            <groupId>net.logstash.logback</groupId>
            <artifactId>logstash-logback-encoder</artifactId>
            <version>5.2</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

    </dependencies>

</project>

定义启动类,我们使用XML配置的方式启动ApplicationContext

package com.zaomianbao.spring;

import com.zaomianbao.spring.domain.Student;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Description Spring容器启动类
 * @Author zaomianbao
 * @Date 2019/3/21
 **/
@Slf4j
public class SpringIocStarter {

    public static void main(String[] args) {

        // 用我们的配置文件来启动一个 ApplicationContext
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring.xml");
        log.info("context 启动成功");

        // 从 context 中取出我们的 Bean,而不是用 new MessageServiceImpl() 这种方式
        Student student = context.getBean(Student.class);
        log.info(student.toString());

    }

}

Student实体类

package com.zaomianbao.spring.domain;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * @Description 学生实体
 * @Author zaomianbao
 * @Date 2019/5/13
 **/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Component
public class Student {

    private String name;
    private Integer age;

}

spring.xml


<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
       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"
       default-autowire="byName">

    <context:component-scan base-package="com.zaomianbao.spring"/>

    <bean id="student" class="com.zaomianbao.spring.domain.Student">
        <property name="name" value="zaomianbao1"/>
        <property name="age" value="18"/>
    bean>

beans>

BeanFactoryPostProcessor的自定义实现类BeanFactoryPostProcessorOne

package com.zaomianbao.spring.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

/**
 * @Description bean工厂后置处理器1
 * @Author zaomianbao
 * @Date 2019/5/13
 **/
@Component
@Slf4j
public class BeanFactoryPostProcessorOne implements BeanFactoryPostProcessor {

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory){
        log.info("调用了BeanFactoryPostProcessorOne");
        String[] beanNames = beanFactory.getBeanDefinitionNames();
        for (int i = 0; i < beanNames.length; i++) {
            String beanName = beanNames[i];
            if ("student".equals(beanName)) {
                BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
                MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
                if (propertyValues.contains("name")) {
                    propertyValues.addPropertyValue("name", "zaomianbao2");
                    log.info("修改了name属性初始值为zaomianbao2");
                }
            }
        }
    }
}

运行后控制台打印数据如下

21:48:04.460 [main] INFO com.zaomianbao.spring.config.BeanFactoryPostProcessorOne - 调用了BeanFactoryPostProcessorOne
21:48:04.465 [main] INFO com.zaomianbao.spring.config.BeanFactoryPostProcessorOne - 修改了name属性初始值为zaomianbao2
21:48:04.660 [main] INFO com.zaomianbao.spring.SpringIocStarter - context 启动成功
21:48:04.661 [main] INFO com.zaomianbao.spring.SpringIocStarter - hello zaomianbao
21:48:04.662 [main] INFO com.zaomianbao.spring.SpringIocStarter - Student(name=zaomianbao2, age=18)

可以看到在初始化Spring容器期间,Spring在初始化过程中调用了我们自定义的BeanFactoryPostProcessorOne的postProcessBeanFactory方法。在这个方法内,我们获取了Student这个类的对象的定义BeanDefinition,并且获取Student对象定义的所有属性,并且将name属性的值从xml中配置的"zaomianbao1"修改成了"zaomianbao2",这个在控制台的最后一项可以看到,值已经变成了"zaomianbao2"。

你可能感兴趣的:(后台开发,Spring)