• 刘彬
    2020-02-24
    跟了一下代码,对于为什么static就会生效的个人理解: 上下文refresh后,会调用registerBeanPostProcessors注册各beanPostProcessors。此时demo所在的类并没有初始化为bean。 但是如果要拿到自定义的AutowiredAnnotationBeanPostProcessor,就必须拿到demo的bean后调用beanPostProcessor来拿到这个PostProcessor bean。这就必然导致整个demo配置类先实例化初始化,也就导致@InjectUser注入的bean还没有被AutowiredAnnotationBeanPostProcessor解析,就注入进来了,也就是null。如果加上static,那么就不需要先拿到demo的bean,可以直接调用类方法获取这个AutowiredAnnotationBeanPostProcessor。那么就会导致先拿到processor,后拿到demo的bean。这样demo在初始化的时候,就会正常解析自定义@InjectUser。所以对于同时存在bean的定义和bean的注入的配置类,顺序很容易弄错。
    展开

    作者回复: 给力,就是需要这样盘根问底~

    共 3 条评论
    34
  • Geek_614528
    2020-04-01
    关于 "static" 首先对比 BeanDefinition : 加 static BeanDefinition 中 factoryBeanName=null; 不加 static BeanDefinition 中 factoryBeanName=annotationDependencyInjectionResolutionDemo; 上代码: org.springframework.beans.factory.support.ConstructorResolver#instantiateUsingFactoryMethod 中,下面代码片段: String factoryBeanName = mbd.getFactoryBeanName(); if (factoryBeanName != null) { if (factoryBeanName.equals(beanName)) { throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "factory-bean reference points back to the same bean definition"); } factoryBean = this.beanFactory.getBean(factoryBeanName); // 此处会去先创建类对象,导致注入失败 if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) { throw new ImplicitlyAppearedSingletonException(); } factoryClass = factoryBean.getClass(); isStatic = false; } else { // It's a static factory method on the bean class. if (!mbd.hasBeanClass()) { throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "bean definition declares neither a bean class nor a factory-bean reference"); } factoryBean = null; factoryClass = mbd.getBeanClass(); isStatic = true; } 不加 static,会在创建 Bean beanPostProcessor 的过程中「未创建完成」,先去创建所在类的实例,由于处理 @Autowired 等注解的后置处理器未完成创建,导致字段注入失败。
    展开

    作者回复: 厉害,打破砂锅问到底

    共 3 条评论
    10
  • yes
    2020-03-07
    关于static问题,如果没有标注static的话想要拿到自定义的AutowiredAnnotationBeanPostProcessor,就必须实例化demo类,因为自定义的AutowiredAnnotationBeanPostProcessor是被定义在demo类中的。 但是在实例化demo类InjectUser也同时被处理了,此时还没有自定义的AutowiredAnnotationBeanPostProcessor,因此不认识@InjectUser,因此被注入了null。然后等实例化完了之后自定义的AutowiredAnnotationBeanPostProcessor才拿到。 而定义了static之后,自定义的AutowiredAnnotationBeanPostProcessor就不依托于demo类的实例化,因此在要实例化demo类的时候自定义PostProcessor会先于InjectUser被注入,因此处理InjectUser的时候已经有了自定义BeanPostProcessor

    作者回复: Bingo

    共 4 条评论
    10
  • 谁都会变
    2022-02-25
    static生效能生效。对static标注的Bean会在AbstractApplicationContext的refresh方法调用registerBeanPostProcessors注册了我们使用@Bean定义的AutowiredAnnotationBeanPostProcessors。具体的在PostProcessorRegistrationDelegate的 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);这行代码,有兴趣的可以debug下。

    作者回复: static 字段是不能注入,并不是说Bean 定义

    
    1
  • 周治慧
    2020-03-13
    总结:当demo bean对象初始化时,自定义的beanPostProcessors还未被加载所以不能解析@InjectionUser注解的注入,可以通过static来让静态方法属于类而不实例(即不需要等待demo bean的初始化即可用),因为AnnotationConfigUtils#registerAnnotationConfigProcessors()方法,定义了beanDefinitionRegistry中如果存在AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME bean对象后就不在去创建默认的bean对象,所以当我们将bean的名称改为AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME时对应的@autowired @value @inject注解都不会被解析,此时只有@injectionUser被解析,如果我们不将bean名称改为AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME此时两个AutowiredAnnotationBeanPostProcessor同时存在自定义注解@injectionUser和@Autowired同时可以被解析 老师有个问题,就是当自定义bean定义为非静态时,此时默认的AutowiredAnnotationBeanPostProcessor会被初始化,但是为啥demo对象实例化的时候对应的user等非@InjectionUser修饰的主键的属性未被依赖注入呢?
    展开

    作者回复: 并非如此,AutowiredAnnotationBeanPostProcessor 是处理依赖注入,和 @Bean 定义为静态或非静态没有关系,这个例子主要是因为 @Bean 定为为非静态,所以导致了问题

    共 2 条评论
    1
  • 胡化敏
    2020-02-29
    这个扩展 在开发中有哪里好处,为什么要扩展了

    作者回复: 主要是为了让小伙伴们了解到 Spring 内部依赖注入的扩展机制,应对未来可能的机会。重复发明轮子是人的天性,另外一方面是了解其他是如何重复发明轮子的~

    
    1
  • 艳阳天
    2021-11-17
    小马哥有个问题麻烦咨询下,NamespaceHandler 这个类可以用来扩展这个我是清楚的,并且知道默认我们扩展是实现init()类,然后解析标签用parse()方法,我想问下,我写个什么样的demo可以走到第三个方法上面,这个包装的decorate()方法,我看默认解析bean的时候有地方能用到,但是解析Url是默认那个,走不到这个方法,小马哥能举个例子吗?非常感谢

    作者回复: 可参考:https://github.com/apache/dubbo/blob/3.2/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java

    共 2 条评论
    
  • Wheat Liu
    2021-02-20
    配置一个新的AutowiredAnnotationBeanPostProcessor的原理: 会让上下文在刷新(refresh)的注册后置处理器(PostProcessorRegistrationDelegate#registerBeanPostProcessors())步骤中,使用DefaultListableBeanFactory#getBeanNamesForType()把所有后置处理器(BeanPostProcessor类型的bean)都找出来。自定义AutowiredAnnotationBeanPostProcessor其实和内置的AutowiredAnnotationBeanPostProcessor地位相同

    作者回复: 666

    
    
  • 王娜
    2021-02-18
    小马哥,为什么不加static不起作用,能不能这样理解? 因为当 @Bean 方法定义是非 static 的话,那么它的初始化依赖于所属类 Bean 的初始化,而处理Demo属性的注入@Autowired属于Demo这个Bean初始化的一个环节,所以当 @Autowired 字段发生时,BeanPostProcessor后置处理器并没有创建好,所以@Autowired注解会失效。 采用static,将创建BeanPostProcessor后置处理器提前到了初始化Demo这个Bean之前,所以能够处理@Autowired注解

    作者回复: 对的

    
    
  • Dougleas
    2021-01-29
    @Configuration public class AutowiredAnnotationDependency { @Bean @Order(Ordered.LOWEST_PRECEDENCE - 3) public static AutowiredAnnotationBeanPostProcessor definedAutowire() { AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor(); Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4); autowiredAnnotationTypes.add(MyAutowired.class); autowiredAnnotationTypes.add(Autowired.class); autowiredAnnotationTypes.add(Value.class); autowiredAnnotationTypes.add(Inject.class); beanPostProcessor.setAutowiredAnnotationTypes(autowiredAnnotationTypes); return beanPostProcessor; } } @Component public class AnnotationLookup { @Autowired private User user; @Autowired private Map<String, User> userMap; @MyAutowired private Optional<ChildUser> optionalUser; @Autowired private ObjectProvider<User> userObjectProvider; @Qualifier("childUser") @Inject private User injectUser; } 马哥,在boot工程下没有加static为什么是可以的?
    展开

    作者回复: 因为 Spring Boot 引导类和这个不一样,主要看引导类所在的位置,main 方法和 @Bean 定义或者@Component 在同一个中,最好增加 static 让其提前被解析并形成 BeanDefinition。

    共 2 条评论
    