BeanPostProcessor Bean的后置处理器

测试环境

  • JDK 1.8
  • Spring 5.2.13.RELEASE

BeanPostProcessor 有什么用

BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口。

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;
	}
}

在Spring针对Bean做修饰和实例化前后,可供程序员对某些Bean的生成做干扰操作。

Demo

创建三个类,分别是User.javaPersion.javaUserProcessor.java

import org.springframework.stereotype.Component;

@Component
public class User {
    
    
    private String name;

    public String getName() {
    
    
        return name;
    }

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

class Persion {
    
    
}
import org.springframework.stereotype.Component;

/**
 * 只用于BeanPostProcessor更改User返回bean类型操作
 */
@Component
public class UserProcessor {
    
    
}

创建扫描类ScanConfig.java,提供Spring扫描注入Bean的配置操作。

import org.springframework.context.annotation.ComponentScan;

/**
 * 只扫描  beanPostProcessors  包下的 Bean
 */
@ComponentScan("beanPostProcessors")
public class ScanConfig {
    
    
}

创建BeanPostProcessorTest.java,实现BeanPostProcessor 接口

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * 一个 BeanPostProcessor 的干扰测试类
 */
@Component
public class BeanPostProcessorTest implements BeanPostProcessor {
    
    

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    
        return null;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    
    
    	// 由于两个类上加了 @Component ,为了测试区分,当发现是 UserProcessor 对象时,则将bean改掉!
        if("userProcessor".equalsIgnoreCase(beanName)){
    
    
            return new Persion();
        }
        // 其他照旧
        return null;
    }
}

创建测试类,编写测试代码:

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {
    
    
    public static void main(String[] args) {
    
    
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanConfig.class);
        System.out.println(applicationContext.getBean("user",User.class));

        System.out.println(applicationContext.getBean("userProcessor",UserProcessor.class));
    }
}

运行结果

在这里插入图片描述

总结

由于干扰类并未对User类的生成造成干扰操作,所以获取applicationContext.getBean("user",User.class)无异常。

但是在构建UserProcessor实例化bean操作后,将其bean的实例化对象更改为new Persion(),导致applicationContext.getBean("userProcessor",UserProcessor.class)获取到的实例化对象的类型无法对应!

Exception in thread "main" org.springframework.beans.factory.BeanNotOfRequiredTypeException: 
Bean named 'userProcessor' is expected to be of type 'beanPostProcessors.
UserProcessor' but was actually of type 'beanPostProcessors.Persion'

期待获取bean名称为userProcessor的类型为beanPostProcessors.UserProcessor
但其实际类型却是beanPostProcessors.Persion

Demo2 设置某些属性的值(类似 @Value)

自定义一个注解@XJ,标注至需要修饰的属性上,同时给定数据值,在测试类中获取对应的属性值。
创建自定义注解:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME) // 运行时生效
@Target(ElementType.FIELD) //只能用于属性上
public @interface XJ {
    
    

    String value() default "";
}

创建需要修饰的类:

import org.springframework.stereotype.Component;

@Component
public class User {
    
    
	
	// 添加自定义注解,并给定其值
    @XJ("xiangjiao")
    private String name;

    public void test(){
    
    
        System.out.println(name);
    }
}

创建影响Spring容器中bean的后置处理类的实现类:

package BeanPostProcessor2;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;

@Component
public class BeanPostProcessorVo implements BeanPostProcessor {
    
    
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    
        return null;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    
    
        // 当此时的bean是 User.class时
        if("user".equalsIgnoreCase(beanName)){
    
    
            // 获取class反射对象
            Class<?> clazz = bean.getClass();
            // 遍历本类其中的属性,如果是获取父类,则是 clazz.getFields()
            for (Field field : clazz.getDeclaredFields()) {
    
    
                // 如果该属性上包含  自定义注解信息
                if (field.isAnnotationPresent(XJ.class)) {
    
    
                    // 拿到注解对象
                    XJ annotation = field.getAnnotation(XJ.class);
                    // 拿到注解中设置的数据
                    String value = annotation.value();
                    // 将数据设置至属性中
                    field.setAccessible(true);
                    try {
    
    
                        field.set(bean,value);
                    } catch (IllegalAccessException e) {
    
    
                        e.printStackTrace();
                    }
                }
            }
        }
        return bean;
    }
}

编写扫描类:

package BeanPostProcessor2;

import org.springframework.context.annotation.ComponentScan;

@ComponentScan("BeanPostProcessor2")
public class ScanConfig {
    
    
}

编写测试类:

package BeanPostProcessor2;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {
    
    
    public static void main(String[] args) {
    
    
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanConfig.class);
        User user = applicationContext.getBean("user", User.class);
        user.test();
    }
}

运行日志:
在这里插入图片描述

代码参考

github 代码Demo
github 代码Demo2

猜你喜欢

转载自blog.csdn.net/qq_38322527/article/details/114261896
今日推荐