Spring BeanPostProcessor实现ApplicationContext注入案例复现

演示思路

  • 实现效果
  • 实现源码
  • Spring重要源码浅析

实现效果

ApplicationContextAware这个接口是我们很好的参考对象, 利用接口获取其内部的applicationContext, 让开发者也能参与扩展.

复现的案例 最终效果为通过注入一个接口, 用户可以拿到类上定义的注解
为了演示的完整性, 添加了业务方法doService()

使用端代码

package cxf.demo.define;

/**
 * @author cxf
 * @create 2019-10-11 22:32
 * @desc 业务接口的定义.
 **/
public interface SystemService {
    void doService();
}
/**
 * @author cxf
 * @create 2019-10-11 22:28
 * @desc A系统获取@AnnotationData 注解信息, 并在业务方法中使用.
 **/
@AnnotationData
@Component
public class ASystemService implements AnnotationDataAware, SystemService {

    private String key;

    public void setAnnotationData(AnnotationData annotationData) {
        key = annotationData.key();
    }

    public void doService() {
        System.out.println(key + " " + getClass() );
    }
}
/**
 * @author cxf
 * @create 2019-10-11 22:28
 * @desc B系统获取@AnnotationData 注解信息, 并在业务方法中使用(注解AnnotationData信息与A系统不同).
 **/
@AnnotationData(key = "BS")
@Component
public class BSystemService implements AnnotationDataAware, SystemService {

    private String key;

    public void setAnnotationData(AnnotationData annotationData) {
        key = annotationData.key();
    }

    public void doService() {
        System.out.println(key + " " + getClass() );
    }
}
/**
 * @author cxf
 * @create 2019-10-11 22:16
 * @desc 注解定义.
 **/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface AnnotationData {

    String key() default "keith";

实现源码

/**
 * @author cxf
 * @create 2019-10-11 22:18
 * @desc 子类实现AnnotationDataAware 这个接口, 即可获得类上的AnnotationData 注解信息.
 **/
public interface AnnotationDataAware extends Aware {
    void setAnnotationData(AnnotationData annotationData);
}
/**
 * @author cxf
 * @create 2019-10-11 22:20
 * @desc 干预bean的生命周期, 实现AnnotationDataAware 接口功能的逻辑代码.
 **/
@Component
public class AnnotationDataAwareProcessor implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    	// 每个spring管理的bean实例化时, 都会走这里
    	// 此处过滤 当bean实现了  AnnotationDataAware接口时, 才执行AnnotationDataAware 的逻辑代码
        if (bean instanceof AnnotationDataAware) {
            AnnotationDataAware annotationDataAware = (AnnotationDataAware) bean;
            AnnotationData annotation = bean.getClass().getAnnotation(AnnotationData.class);
            if (annotation != null) {
                annotationDataAware.setAnnotationData(annotation);
            }
        }
        return bean;
    }
}

测试部分

/**
 * @author cxf
 * @create 2019-10-08 20:20
 * @desc test.
 **/
public class AnnotationSpringTest {

    public static void main(String[] args) {
    	// 通过注解简单搭建了spring的环境
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        // 获取 Spring容器中 beanName - > bean 的集合
        Map<String, SystemService> beansOfType = applicationContext.getBeansOfType(SystemService.class);
		// 遍历调用所有实现 SystemService 接口的bean的业务方法doService
        for (SystemService systemService : beansOfType.values()) {
            systemService.doService();
        }
    }
}

效果实现啦!通过 AnnotationDataAware成功能拿到了@AnnotationData 上的信息在这里插入图片描述

Spring重要源码浅析

写文章时正好正好不是有源码的机器, 所以大家理解理解
在这里插入图片描述

几个重要的点

  1. this.applyBeanPostProcessorsBeforeInitialization(bean, beanName); 这个方法是在对象实例化之后执行的(spring反射调用构造方法)
  2. applyBeanPostProcessorsBeforeInitialization() 和 applyBeanPostProcessorsAfterInitialization() 方法分别是调用 BeanPostProcessor接口 的 before / after … 的两个方法, 但它会拿取 beanFactory中beanPostProcessors这个成员变量(也就是所有的BeanPostProcessor的实例, 包括系统定义的和用户定义的)遍历调用
  3. this.invokeInitMethods(beanName, wrappedBean, mbd); 调用 实现InitializingBean接口的afterPropertiesSet();方法(bean初始化流程之一, 如有@PostConstruct注解的方法会在其先调用, [@PostConstruct是在第一点中调用的], 本文就不解析了, 有兴趣的可私聊我讨论)

到这里就没啦!! 关于Spring还有很多的扩展点, 本人利用Spring在公司中也做了不少事情, 可以说Spring这柄利器挥得好, 加班从此路人. 本人对Spring的源码也有一些研究, 欢迎大家指点.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值