简单介绍
这篇文章我们实现一个自定义的注解,简单了解一下基于Spring实现注解的基本思路。
开始
准备注解
怎么建项目就不用说了,但凡已经开始了解自定义注解的应该都会了。自定义注解当然开始就是准备一个注解了
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SampleAnnotation {
// 表示是哪个应用
String group();
// 表示是哪个文件
String file();
}
1、@Target这行说明我们自定义的注解只能使用在方法上,其他选项请自行脑补,不展开了。
2、@Retention这行说明我们的注解要保留到运行时,其他选择可以只保留到编译时,一样自行脑补。
所以我们现在定义的是一个能在方法上加的、运行时依然存在的、有两个属性(group、name)的 注解。
所以我们使用的时候就是在一个方法上添加 @SampleAnnotation(group = “app1”, file = “xxx.properties”)
处理逻辑
注解定义了其实没有什么用,加上之后啥效果都没有,重点是我们怎么处理这个注解。
Spring给我们提供了一个扩展BeanPostProcessor,也叫前后置处理器,我们可以用它在bean初始化前后处理一些东西。
我们这次是要在bean初始化之后做些事情。
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.*;
public class SampleBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Class<?> clazz = bean.getClass();
Method[] methods = clazz.getMethods();
for (Method method : methods) {
Annotation annotation = method.getAnnotation(SampleAnnotation.class);
if (annotation != null) {
try {
// 开始执行这个有注解的方法
method.invoke(bean, new HashMap<>());
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("执行错误");
}
// throw new RuntimeException("这个是测试的,如果抛出异常,spring初始化就会停止,可以快速发现问题");
}
}
return bean;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
postProcessAfterInitialization方法是我们这次的重点,这个方法会在bean初始化完成之后执行,我们实现的功能是取出所有public修饰的含有SampleAnnotation注解的方法,然后执行它。
配置
然后这个SampleBeanPostProcessor是要配置为一个bean的
<bean id="sampleBeanPostProcessor" class="li.dongpo.tc.service.SampleBeanPostProcessor" />
测试代码
public class Application {
public static void main(String[] args) throws InterruptedException {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
System.out.println("context初始化完成,开始获取bean");
}
}
执行输出
拉取到配置文件 {}
context初始化完成,开始获取bean
代码
我把代码上传到了github上,感兴趣的同学可以自行下载参照。 https://github.com/remainer-com/spring-sample 参见 spring-annotation-sample 模块