BeanPostProcessor后置处理器

后置处理 Bean : BeanPostProcessor的使用

在bean对象初始化之前和之后 (bean从容器中返回给我们之前): 来做某些事情

  • BeanPostProcessor 作用:对 Spring 工厂所创建的对象,进行再加工。(AOP 的底层实现)
  • 后置处理 Bean 原理分析
  • 程序员实现 BeanPostProcessor 接口中规定的两个方法:
// bean初始化之前调用
public Object postProcessBeforeInitialization(Object bean, String beanName) {
    return bean;
}

作用:Spring 创建完对象,并进行注入后,可以运行 Before ⽅法进行加工;

通过方法的参数获得 Spring 创建好的对象,最终通过返回值交给 Spring 框架。

// bean初始化之后调用
public Object postProcessAfterInitialization(Object bean, String beanName) {
    return bean;
}

作⽤:Spring 执行完对象的初始化操作后,可以运行 After ⽅法进行加工;

通过方法的参数获得 Spring 创建好的对象,最终通过返回值交给 Spring 框架。
实战中:很少处理 Spring 的初始化操作,没有必要区分 Before,After。只需要实现其中一个,建议是 After 方法即可。

BeanPostProcessor 开发步骤

类实现 BeanPostProcessor 接口


// 在初始化方法之前和之后执行下面两个方法
//@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Category category = (Category) bean;
        category.setName("yusael");
        return category;
    }

}

Spring 配置文件中进行配置

  • <bean id="myBeanPostProcessor" class="com.yusael.beanpost.MyBeanPostProcessor"/>
  • 细节:BeanPostProcessor 会对 Spring 工厂创建的所有对象进行加工。如果工厂创建了多个不同的对象,要注意区别传入的对象:
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof  Category) {
        Category category = (Category) bean;
        category.setName("yusael");
        return category;
    }
    return bean;
}

在这里插入图片描述

在这里插入图片描述

BeanPostProcessor原理

下面代码可以证明:BeanPostProcessor是在bean初始化前后来做事情

这块代码在initializeBean方法内
在这里插入图片描述

  • 在applyBeanProcessorsBeforeInitialization方法中遍历所有的BeanPostProcessor(包括实现类); 如果返回null, 表示不会执行后面的BeanPostProcessor了; 把所有的BPP在bean初始化之前的操作都执行完
    在这里插入图片描述
  • 执行自定义初始化操作 invokeInitMethods方法
  • 在applyBeanProcessorsAfternitialization方法中遍历所有的BeanPostProcessor(包括实现类); 如果返回null, 表示不会执行后面的BeanPostProcessor了; 把所有的BPP在bean初始化之后的操作都执行完

BeanPostProcessor原理
在这里插入图片描述

BeanPostProcessor在Spring底层的使用

在这里插入图片描述

ApplicationContextAwareProcessor

  • class ApplicationContextAwareProcessor implements BeanPostProcessor

该processor给ApplicationContextAware接口导入了Spring中所有的bean; 我们实现ApplicationContextAware就可以拿到Spring容器中所有的bean

ApplicationContextAwareProcessor会在

class ApplicationContextAwareProcessor implements BeanPostProcessor {

	private final ConfigurableApplicationContext applicationContext;

	private final StringValueResolver embeddedValueResolver;


	/**
	 * Create a new ApplicationContextAwareProcessor for the given context.
	 */
	public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
		this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
	}


	@Override
	@Nullable // 在bean初始化之前来执行
	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
		AccessControlContext acc = null;

		if (System.getSecurityManager() != null &&
				(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
						bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
						// 首先判断bean是否实现了ApplicationContextAware
						bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			// ... 省略
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			// 然后把这个bean转换为ApplicationContextAware, 将IoC容器
//			(this.applicationContext)设置到setApplicationContext()中
			// 所以在我们类实现ApplicationContextAware接口的实现方法中,拿到IoC容器
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		return bean;
	}
}

测试

@Component
public class User implements ApplicationContextAware {
    private ApplicationContext ac;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.ac = applicationContext;
    }

    public ApplicationContext getContext() {
        return ac;
    }

    public <Y> Y getBean(Class<Y> clazz) {
        return ac.getBean(clazz);
    }
}
    @Test
    public void test() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig6.class);
//        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
//        for (String name : beanDefinitionNames) {
//            System.out.println(name);
//        }
//        System.out.println(ac.getBean("rainBow"));

        User user = ac.getBean(User.class);
        ApplicationContext context = user.getContext();
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        System.out.println("-----------------------------");
        Red bean = user.getBean(Red.class);
        System.out.println(bean);
    }


org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
appConfig6
customer
user
red
blue
rainBow
-----------------------------
com.baizhiedu.bean.Red@6c4980d3
除了上面的ApplicationContextAwareProcessor; 还有给bean赋值, 注入其他组件, @Autowird, 生命周期注解, @Async 等 实现的原理; 都是采用xxxBeanPostProcessor来实现的

实现XxxAware, 使用Spring容器底层的一些组件

自定义的组件(bean) 想要使用Spring容器底层的一些组件(ApplicationContext, BeanFactory…等);

  • 我们自定义的组件 实现XxxAware; 实现他们的一些接口方法,
    在创建自定义组件对象的时候, 会调用接口规定的方法注入相关组件

实现XxxAware, 把Spring底层的一些组件注入到自定义的Bean中

@Component
public class TestAware implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {

    private ApplicationContext applicationContext;

    // 将当前bean的名字返回
    @Override
    public void setBeanName(String s) {
        System.out.printf("当前bean的名字:%s%n", s);
    }

    // 返回IoC容器
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        System.out.println("IoC容器:" + this.applicationContext);
    }

    // 用来解析Spring中表达式的
    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        System.out.println(resolver.resolveStringValue("你好, ${os.name}, my age is #{2 * 12}"));
    }
}
@Test
public void test02() {
    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig7.class);
    TestAware bean = ac.getBean(TestAware.class);
    System.out.println(bean);
}
当前bean的名字:testAware
你好, Mac OS X, my age is 24
IoC容器:org.springframework.context.annotation.AnnotationConfigApplicationContext@7714e963, started on Fri Apr 15 17:49:02 CST 2022

从下面图可以看出, 在bean返回之前就做了对应的处理工作
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

white camel

感谢支持~

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

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

打赏作者

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

抵扣说明:

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

余额充值