postProcessMergedBeanDefinition()【MergedBeanDefinitionPostProcessor接口提供】找注入点
1.postProcessMergedBeanDefinition这个方法先执行其实就是去找注入点,传入BeanDefinition,beanType,beanName【根据当前bean的类1. 哪些属性上加了@Autowired注解 2.哪些set方法上加了@Autowired注解】。拿到InjectionMetadata meta是当前这个类的所有注入点封装起来的对象,集合然后缓存起来。
2.找注入点过程
do-while循环(子类找完找父类){
遍历字段
①首先会判断是不是一个候选类:比如String类就不是,如果某个类是以java.开头的就不需要找注入点,java.开头的类代表Java平台的核心类,以确保Spring容器的职责明确,专注于它应该管理的组件
②看上面有没有@Value,@Autowired,@Inject注解【spring启动时候就初始化好了的】最终就会加到集合currElements里面(就说明你是一个注入点)。static修饰的字段没有把它当做是一个注入点
spring就不会给这个属性赋值,这个属性是属于类的,而不是一个具体的bean对象的。原因:对于原型bean注入原型的对象,两次注入的对象不是同一个,但是你是声明的static的啊,不允许修改的。
③针对@Autowired注解解析如果require=true,然后找不到bean就会报错。
遍历方法
①看上面有没有@Value,@Autowired,@Inject注解【spring启动时候就初始化好了的】最终就会加到集合currElements里面(就说明你是一个注入点)。static修饰的字段没有把它当做是一个注入点。【就算方法参数是0,spring也是会把他当做一个注入点的,不过不会找对象,而是直接调用该方法】
②如果有泛型。通过反射这里会拿到2个注入点,这是不对的,所以会排除掉桥接方法,然后找到被桥接的那个方法去判断。
}
最后都加到集合里去
=================================================================================
2.1通过反射这里会拿到2个注入点,这是不对的,所以会排除掉桥接方法,然后找到被桥接的那个方法(自己实现的那个方法)去判断。
Parent 类有一个泛型方法 getValue(),而 Child 类继承自 Parent 并指定泛型类型为 String,同时重写了 getValue() 方法。
问题出现在类型擦除时。Java 泛型在编译时会进行类型擦除,这意味着泛型类型信息在运行时是不可用的。因此,编译后的 Parent 类中的 getValue() 方法返回的是 Object 类型,而不是泛型类型 T。而 Child 类重写的 getValue() 方法返回的是 String 类型。在这种情况下,Child 类实际上并没有重写 Parent 类的 getValue() 方法(因为返回类型不同),这会导致多态的问题。
为了解决这个问题,编译器会在 Child 类中创建一个桥接方法,这个桥接方法的返回类型与父类方法相同(即 Object),并在内部调用重写后的 getValue() 方法。这样,当通过 Parent 类型的引用调用 getValue() 方法时,实际上调用的是桥接方法,该方法会转而调用 Child 类中重写的 getValue() 方法。
实际的桥接方法可能会像这样:
=================================================================================
postProcessProperties()【SmartInstantiationAwareBeanPostProcessor接口里实现的InstantiationAwareBeanPostProcessor接口提供的postProcessProperties(){处理属性方法}】
1.从上面的缓存中取出所有注入点然后挨个遍历。
如果是字段(具体下篇补充)
①根据字段的名字和类型去找值,找到后值value以后,直接调用反射给属性赋值
如果是方法(具体下篇补充)
①如果当前的BeanDefinition里设置的属性包括了该注入点对应的那个属性,就跳过注入(只在方法里判断了)
只要实现了MergedBeanDefinitionPostProcessor接口这里可以修改BeanDefinition的属性赋值【先执行】
②最后返回个数组,然后执行加了@Autowired的方法