演示思路
- 实现效果
- 实现源码
- 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重要源码浅析
写文章时正好正好不是有源码的机器, 所以大家理解理解
几个重要的点
- this.applyBeanPostProcessorsBeforeInitialization(bean, beanName); 这个方法是在对象实例化之后执行的(spring反射调用构造方法)
- applyBeanPostProcessorsBeforeInitialization() 和 applyBeanPostProcessorsAfterInitialization() 方法分别是调用 BeanPostProcessor接口 的 before / after … 的两个方法, 但它会拿取 beanFactory中beanPostProcessors这个成员变量(也就是所有的BeanPostProcessor的实例, 包括系统定义的和用户定义的)遍历调用
- this.invokeInitMethods(beanName, wrappedBean, mbd); 调用 实现InitializingBean接口的afterPropertiesSet();方法(bean初始化流程之一, 如有@PostConstruct注解的方法会在其先调用, [@PostConstruct是在第一点中调用的], 本文就不解析了, 有兴趣的可私聊我讨论)
到这里就没啦!! 关于Spring还有很多的扩展点, 本人利用Spring在公司中也做了不少事情, 可以说Spring这柄利器挥得好, 加班从此路人. 本人对Spring的源码也有一些研究, 欢迎大家指点.