【问题标题】:What is the Spring DI equivalent of CDI's InjectionPoint?什么是 CDI 的 InjectionPoint 的 Spring DI 等价物?
【发布时间】:2012-03-29 22:18:39
【问题描述】:

我想创建一个 Spring 的 bean producer 方法,它知道是谁调用了它,所以我从以下代码开始:

@Configuration
public class LoggerProvider {

    @Bean
    @Scope("prototype")
    public Logger produceLogger() {
        // get known WHAT bean/component invoked this producer 
        Class<?> clazz = ...

        return LoggerFactory.getLogger(clazz);
    }
}

我如何获得想要注入 bean 的信息?

我正在 Spring 世界中寻找与 CDI's InjectionPoint 等价的东西。

【问题讨论】:

    标签: spring dependency-injection java-ee-6 cdi producer


    【解决方案1】:

    Spring 4.3.0 为 bean 生成方法启用 InjectionPoint 和 DependencyDescriptor 参数:

    @Configuration
    public class LoggerProvider {
    
        @Bean
        @Scope("prototype")
        public Logger produceLogger(InjectionPoint injectionPoint) {
            Class<?> clazz = injectionPoint.getMember().getDeclaringClass();
    
            return LoggerFactory.getLogger(clazz);
        }
    }
    

    顺便说一句,the issue for this feature SPR-14033 链接到 a comment on a blog post 链接到这个问题。

    【讨论】:

    【解决方案2】:

    据我所知,Spring没有这样的概念。

    那么唯一知道处理点的就是BeanPostProcessor


    例子:

    @Target(PARAMETER)
    @Retention(RUNTIME)
    @Documented
    public @interface Logger {}
    
    public class LoggerInjectBeanPostProcessor implements BeanPostProcessor {   
        public Logger produceLogger() {
            // get known WHAT bean/component invoked this producer
            Class<?> clazz = ...    
            return LoggerFactory.getLogger(clazz);
        }
    
    
        @Override
        public Object postProcessBeforeInitialization(final Object bean,
                final String beanName) throws BeansException {
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(final Object bean,
                final String beanName) throws BeansException {
    
            ReflectionUtils.doWithFields(bean.getClass(),
                    new FieldCallback() {
                         @Override
                         public void doWith(final Field field) throws IllegalArgumentException, IllegalAccessException {
                             field.set(bean, produceLogger());
                         }
                    },
                    new ReflectionUtils.FieldFilter() {
                         @Override
                         public boolean matches(final Field field) {
                              return field.getAnnotation(Logger.class) != null;
                         }
                    });
    
            return bean;
        }
    }
    

    【讨论】:

    • 谢谢拉尔夫!好的,所以只要在任何地方注入任何 bean,就会调用这个 BeanPostProcessor。有什么方法可以识别要注入的 什么 bean?我的意思是我得到了:postProcessBeforeInitialization(Object bean, String beanName) 其中bean 是一个想要进行注入的bean(我在我的问题中问过的 who 部分),beanName 是@ 987654327@ 姓名。现在我不知道 bean 中的哪个字段希望进行注入 - 换句话说,我不知道注入的 bean 是 LoggerProvider 还是其他。
    • 据我所知,后处理器是在创建 bean 之后调用的! (不在任何地方注射)。想法是在该 bean 后处理器之上实现您自己的小型注入框架。
    • 好的,所以每当创建 bean 时都会调用 BeanPostProcessor 实现器。所以,你的想法是实现postProcessBeforeInitialization 和例如扫描具有我的自定义注释的字段(比如说@Logger),并通过反射,使用我自己的自定义逻辑初始化此类字段。这是你的方法还是我太复杂了?再次感谢!
    • @Piotr Nowicki:是的,但这真的很容易,而且工作量不大。请参阅我添加的示例。 (我没有测试过那段代码,但它应该给你一个好主意,扩展 Spring 是多么容易,以及 spring utils 是多么强大。)
    猜你喜欢
    • 1970-01-01
    • 2013-07-22
    • 2016-11-19
    • 1970-01-01
    • 2016-04-13
    • 2014-06-12
    • 1970-01-01
    • 2022-11-28
    • 1970-01-01
    相关资源
    最近更新 更多