【问题标题】:Configuring Spring to ignore dependencies annotated with @Inject配置 Spring 以忽略使用 @Inject 注释的依赖项
【发布时间】:2016-10-02 05:49:57
【问题描述】:

我有一个 EJB 类,我需要在其中注入两个 bean - 一个应该由 EJB 容器注入,另一个是 Spring 容器。

@Stateless
@Interceptors(SpringBeanAutowiringInterceptor.class)
@LocalBean
public class SomeClass {

    @Inject
    private EJBClass a;

    @Autowired
    private SpringComponent b;

}

这里,Spring 拦截器试图拦截 bean 'a' 的注入,但它失败了。我希望 EJB 容器注入 bean 'a' 和 Spring 容器注入 bean 'b'。

请告诉我一条出路。

【问题讨论】:

  • 如果您使用的是 Spring 3.0+,为什么不直接使用 @Inject 而不是 @Autowired?另见 a.o. this Mkyong article.
  • 你可以试试Spring的exclude-filter:<context:exclude-filter type="annotation" expression="javax.inject.Inject"/>。我不确定它是否会在字段级别检测到该注释,但文档说它将与注释呈现的类型级别一起使用。值得一试

标签: spring jakarta-ee dependency-injection ejb cdi


【解决方案1】:

通过自定义SpringBeanAutowiringInterceptor 类,可以将带有@Inject 注释的依赖项排除在自动关联之外。

要了解幕后发生的事情,请查看源代码 SpringBeanAutowiringInterceptor.java -

/**
 * Actually autowire the target bean after construction/passivation.
 * @param target the target bean to autowire
 */
protected void doAutowireBean(Object target) {
    AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
    configureBeanPostProcessor(bpp, target);
    bpp.setBeanFactory(getBeanFactory(target));
    bpp.processInjection(target);
}

doAutowireBean 的第一行,创建了AutowiredAnnotationBeanPostProcessor 的新实例。这里配置了一组要扫描的自动连接依赖的注解。

/**
 * Create a new AutowiredAnnotationBeanPostProcessor
 * for Spring's standard {@link Autowired} annotation.
 * <p>Also supports JSR-330's {@link javax.inject.Inject} annotation, if available.
 */
@SuppressWarnings("unchecked")
public AutowiredAnnotationBeanPostProcessor() {
    this.autowiredAnnotationTypes.add(Autowired.class);
    this.autowiredAnnotationTypes.add(Value.class);
    try {
        this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
                ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
        logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
    }
    catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}

因为,默认情况下,@Inject 注释配置为 spring 扫描标记为@Inject 的各个依赖项并尝试自动连接它们。

要排除 @Inject 带注释的依赖项,请在自定义类下方编写。

public class CustomSpringBeanAutowiringInterceptor extends SpringBeanAutowiringInterceptor {

    /**
     * Template method for configuring the
     * {@link AutowiredAnnotationBeanPostProcessor} used for autowiring.
     * @param processor the AutowiredAnnotationBeanPostProcessor to configure
     * @param target the target bean to autowire with this processor
     */
    protected void configureBeanPostProcessor(AutowiredAnnotationBeanPostProcessor processor, Object target) {
        Set<Class> annotationsToScan = new HashSet<Class>();
        annotationsToScan.add(Autowired.class);
        annotationsToScan.add(Value.class);
        processor.setAutowiredAnnotationTypes(annotationsToScan);

    }
}

这里configureBeanPostProcessor钩子用于自定义bean后处理器,以便仅包含我们需要自动连接的那些注释。

在代码中应用这个自定义类作为拦截器后,可以实现所需的行为

@Stateless
@Interceptors(CustomSpringBeanAutowiringInterceptor.class)
@LocalBean
public class SomeClass {

@Inject
private EJBClass a;

@Autowired
private SpringComponent b;

}

如果您遇到任何问题,请在 cmets 中告知。还可以随意优化认为合适的代码,并原谅任何编译/格式问题。

【讨论】:

  • 您是否能够实现所需的行为?
  • 你有 Spring 5 的解决方案吗? SpringBeanAutowiringInterceptor 不再存在。也许您还可以看到我的问题stackoverflow.com/questions/59582720/…,在不同的环境中,我使用不同的解决方案进行管理,但不知何故,我觉得这是 Spring 的不足之处,应该由他们的开发人员解决。
  • documentation看来,该课程仍然可用。尝试使用这个时是否遇到任何编译/运行时错误?
【解决方案2】:

使用@EJB注解注入EJB

【讨论】:

    猜你喜欢
    • 2016-08-07
    • 1970-01-01
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 2017-05-04
    相关资源
    最近更新 更多