2012-03-13 108 views
12

我想创建一个Spring的bean的制作方法,它知道谁调用它,所以我已经开始用下面的代码:什么是CDI的InjectionPoint的Spring DI等价物?

@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的信息注射?

我正在寻找一些在春季世界相当于CDI's InjectionPoint

回答

6

据我所知,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; 
    } 
} 
+0

谢谢拉尔夫!好的,只要有任何bean被注入到任何地方,就会调用这个BeanPostProcessor。有什么方法可以识别**要注入的bean是什么?我的意思是我得到了:'postProcessBeforeInitialization(Object bean,String beanName)'其中'bean'是一个需要进行注入的bean(我在问题中已经问过**的**部分),'beanName '是'bean'的名字。现在我不知道'bean'中的哪个字段想要进行注入 - 换句话说,我不知道注入的bean是否是LoggerProvider或别的东西。 – 2012-03-14 13:04:34

+0

正如我所了解的那样,后处理程序在创建bean后被调用! (没有注入任何地方)。这个想法是在豆后处理器之上实现你自己的小型注入框架。 – Ralph 2012-03-14 13:34:28

+0

好的,所以每当创建一个bean时都会调用BeanPostProcessor实现者。所以,你的想法是实现'postProcessBeforeInitialization'和扫描具有我自定义注释的字段(让我们说'@ Logger'),并通过反射,使用我自己的自定义逻辑来初始化此字段。这是你的方法还是我太复杂了?再次感谢! – 2012-03-14 13:47:34

15

弹簧4.3.0使得用于生产豆方法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可链接到这个问题。

+0

如果我将它注入另一个bean,它也被定义为原型,那么这不会为该bean的每个实例创建一个记录器,而不是共享一个静态实例? – 2017-01-24 10:50:20

+1

@ RupertMadden-Abbott日志记录框架通常会缓存记录器。例如,查看关于SLF4J日志记录框架的这个问题:[在静态和非静态上下文中创建SLF4J记录器的开销是多少?](http://stackoverflow.com/questions/10345109/whats-the-overhead-of -creating-A-SLF4J记录器 - 在静电-VS-非静态上下文) – 2017-01-24 13:31:44