如 @Autowire @Value 等是什么时候执行,在那个类,什么时候触发的。
那么@Autowire @Value 是什么时候放入的呢
1、通过Ctrl+Shift+R进行全局查找
查找到后就打断点
2、debug进来,通过调用栈进行反推
3、Autowired和Value类都放入集合中
4、从调用栈中发现通过构造函数创建对象时加入的
通过doCreateBean开始看吧
因为上面经过层层调用都是通过构造方法去创建实例的。上面已经调用无参构造创建了实例
那么返回的就是这个实例对象。实例里的集合包含着Autowired和Value类
AutowiredAnnotationBeanPostProcessor 类,这个postProcessor的服务会处理@Autowired 和@Value来个注解
那么如何获取里面的属性值的呢?
1、全局快速搜索,并打断点
2、然后debug进行发现没得哦,
好像没有进入任何的debug断点。那么只能重新从刚刚加入的断点处继续。
换一个思路,刚刚Value和Autowirted都加入到了集合,那么就可能会用到这个结合的啊
所以在所有在出现集合的地方打断点。再重新debug进来
3、重新debug进来,进到一个遍历autowiredAnnotationTypes的方法里面
到这里就能得到注解对应的属性,及对应的值了。那么怎么晓得注解什么时候触发呢?
4、结合调用栈进行反推
重点:到此,整个第4点通过反推,就晓得如何获取其目标类的属性(通过反射 获取遍历获取所有属性),获取到属性后,通过lambda表达式中的findAutowiredAnnotation()方法去获取对应的属性的值
5、再看如何通过属性获取注解上面的值
从上面第4点的反推中,发现通过类的全限定类名,再运用反射获取属性的方式。取出属性,及属性上的值。
哪里有获取到注解上面的值呢?
6、看返回的结果是什么
从截图发现,返回的值就是注解上面的值,而且是通过参数传入的,只不过通过这个方法进行获取而已。
结论,通过上面的反推3,看出,通过反射,获取到了各个属性及其属性上对应注解的值
那么如何通过参数获取的需要的注解的值
那么@Autowire @Value什么时候触发执行的呢?
通过调用栈反推, 看名字, 找自动元数据
如何实现自定义的注解
然后发现网上这个写的挺详细的,拷贝下来以便加深理解,及复习
1、自定义@MyValue注解类
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyValue {
String value() default "";
}
2、自定义使用@MyValue注解的属性的类
@Component
@Data
public class Car {
@MyValue(value = "布加迪")
String name;
@MyValue(value = "6666w")
String price;
static {
System.out.println("static car...");
}
}
3、自定义后置处理器 MyPostProcessor
@Component
public class MyPostProcess implements SmartInitializingSingleton,BeanFactoryPostProcessor {
BeanFactory beanFactory;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("this is factory...");
this.beanFactory = beanFactory;
}
@Override
public void afterSingletonsInstantiated() {
System.out.println("process afterSingletons...");
// 处理@MyValue注解
Car car = beanFactory.getBean(Car.class);
// 通过对类的Class对象进行反射,获取其属性
Stream.of(Car.class.getDeclaredFields())
// 如果注解的属性不为空
.filter(field -> field.getAnnotation(MyValue.class) != null)
// 用lambda表达式,通过反射获取注解及其属性
.forEach(field -> {
MyValue myValue = field.getAnnotation(MyValue.class);
try {
field.set(car,myValue.value()); // 属性注入.
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// 设置属性
// System.out.println(field.getName());
//
//1. 方法2,反射找到对应的set方法做属性的设置
/*String fieldName = field.getName();
Class<?> type = field.getType();
String setMethodName = "set".concat(fieldName.substring(0,1).toUpperCase()).concat(fieldName.substring(1));
try {
Method method = Car.class.getMethod(setMethodName, type);
method.invoke(car,myValue.value());
} catch (Exception e) {
e.printStackTrace();
}*/
});
System.out.println("car: "+ car);
}
}
打印结果: Car(name=布加迪, price=6666w) 完成自定义属性注解.
这里需要重点说如一下,自定义后置处理器,实现SmartInitializingSingleton,BeanFactoryPostProcessor 接口,需要重写postProcessBeanFactory() 和 afterSingletonsInstantiated() 方法
其中postProcessBeanFactory() 方法块,在sping初始化bean之前就会调用执行
afterSingletonsInstantiated() 方法会在完成bean的创建及管理之后执行.
[
](https://blog.csdn.net/mapeng765441650/article/details/105477160/)
网上对getDeclaredAnnotations说的解析
java.lang.reflect.Method.getDeclaredAnnotations()方法返回该元素上直接存在的所有注释
方法的用法
主要是:
Method[] methods = SampleClass.class.getMethods(); // 获取所有方法
Annotation[] annotations = methods[0].getDeclaredAnnotations();// 通过反射获取方法上的注解
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
public class MethodDemo {
public static void main(String[] args) {
Method[] methods = SampleClass.class.getMethods();
Annotation[] annotations = methods[0].getDeclaredAnnotations();
for(Annotation annotation : annotations){
if(annotation instanceof CustomAnnotation){
CustomAnnotation customAnnotation = (CustomAnnotation) annotation;
System.out.println("name: " + customAnnotation.name());
System.out.println("value: " + customAnnotation.value());
}
}
}
}
@CustomAnnotation(name="SampleClass", value = "Sample Class Annotation")
class SampleClass {
private String sampleField;
@CustomAnnotation(name="getSampleMethod", value = "Sample Method Annotation")
public String getSampleField() {
return sampleField;
}
public void setSampleField(String sampleField) {
this.sampleField = sampleField;
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface CustomAnnotation {
public String name();
public String value();
}
得到的结果如下:
name: getSampleMethod value: Sample Method Annotation
[
](https://blog.csdn.net/mapeng765441650/article/details/105477160/)
时序图
反射的相关类详解
https://www.yiibai.com/javareflect/javareflect_method_getdeclaredannotations.html