SpringIOC中的后处理器

SpringIOC中的后处理器

beanFactory后处理器

beanFactory后处理器,是为beanFactory而服务的,比如某些后处理器是为了增加各种对bean的定义而产生的,比较熟悉的有解析各种注解的后处理器、解析xml文件的后处理器。

常见的解析注解的BeanFactory后处理器,通过调用ApplicationContext实例对象中的方法registerBean(),将后处理器添加进容器:

// context是ApplicationContext的实例对象,下文中的代码同理
context.registerBean(ConfigurationClassPostProcessor.class);
功能
org.springframework.context.annotationConfigurationClassPostProcessor解析注解:
@Component
@PropertySources
@ComponentScan
@ComponentScans注解的类
@Import注解的类
@ImportResource
@Bean注解方法
org.springframework.context.annotationCommonAnnotationBeanPostProcessor解析注解:
@Resource
@PostConstruct
@PreDestroy
org.springframework.beans.factory.annotationAutowiredAnnotationBeanPostProcessor解析注解:
@Autowired
@Value

注意事项

刷新context对象

在添加完后处理器之后,容器并没有立刻加载所有的bean,如果此时调用获取bean的代码,可能会报错,控制台报错如下:

Exception in thread "main" java.lang.IllegalStateException: org.springframework.context.support.GenericApplicationContext@5e91993f has not been refreshed yet

报错的提示是:还没有将context对象刷新。想解决此类问题,就必须在获取bean之前让容器中把bean加载进去,即让context执行刷新,在获取bean之前执行一行代码即可:

context.refresh();
注入String类型

若IOC注入中,有String类型的对象需要注入,比如下面的代码:

    public String home;
    @Autowired
    public void setHome(@Value("${MAVEN_HOME}") String home) {
        System.out.println("注入了home:" + home);
        this.home = home;
    }

SpringIOC在注入时,会报错,控制台报错如下:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Value(value=${MAVEN_HOME})}

报错的提示大概意思是:没有在容器中找到java.lang.String类型的Bean

这个问题产生的原因,是因为AutowiredAnnotationBeanPostProcessor后处理只能识别@Autowired、@Value并将其注入的需求描述给到容器,但是无法将@Value中的值解析出来给到容器进行注入。想要解决此类问题,需要用到@Autowire注解的候选解析器ContextAnnotationAutowireCandidateResolver.clas,代码如下:

// 添加候选解析器。因为字符串类型在容器中并不是一个Bean,在注入的时候会报错。
// 添加了这个候选解析器,配合使用@Value注解后,就不会报错。如果找不到${}中对应的值,就会原样输出
context.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());

关于为什么会是给BeanFactory设置备选解析器,而不是ApplicationContext。个人的理解是:由于注入之前的解析工作本就应该属于BeanFactory的活儿,而不是ApplicationContext的。因为这个是String对象进入容器之前就应该完成的解析。

bean后处理器

简单的来理解,bean后处理就是基于模版方法设计模式1而产生的,是用于对bean的生命周期各个阶段进行扩展的。

下面是Spring中Bean后处理器的实现案例,也是对bean生命周期进行管理的简单案例:

extends
extends
implements
implements
BeanPostProcessor
+postProcessBeforeInstantiation()
+postProcessAfterInitialization()
InstantiationAwareBeanPostProcessor
+postProcessProperties()
+postProcessPropertyValues()
DestructionAwareBeanPostProcessor
+postProcessBeforeDestruction()
+requiresDestruction()
MyBeanPostProcessor

上方类图中实现类MyBeanPostProcessor.class的定义如下:

// 这个类,就是我们需要实现的类,并将此类的实例添加到spring容器中即可
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
  // 将所有的接口即可实现即可
  // 具体接口方法实现略
}

BeanPostProcessor是Bean后处理器的顶层接口类(根接口类),凡是BeanPostProcessor类型的Bean被添加到spring容器中,都会被视为Bean后处理器,并在bean的生命周期不同阶段调用不同的接口函数。

编辑文章时的测试代码

  • 用于测试beanFactory后处理器的代码在仓库中的demo002 包中。

  • 用于测试bean后处理器的代码在仓库中的demo003包中。


  1. 模版方法设计模式:就是将一些固定的流程提前设计好后,在每一步流程的前或后,加上提前定义好的接口,采用多态的方式调用,这样即可实现动静结合。静即是固定好的流程,动即是调用的接口,接口的实现可根据未来的需求而变化。不论动的部分如何变化,都不需要改变原有设计模式内部的封装。 ↩︎

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值