由使用@Inject的第3方库实现的Spring Bean与Spring的注入机制冲突 [英] Spring Bean implemented by a 3rd party library that uses @Inject conflicting with Spring's injection mechanism

查看:106
本文介绍了由使用@Inject的第3方库实现的Spring Bean与Spring的注入机制冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过第三方库(OWL API)中的类实现 @Bean

I am trying to have a @Bean implemented by a class from a 3rd party library (OWL API).

此实现使用 @Inject 批注。 Spring试图解释它,从而干扰了第三方库的注入机制并避免其按预期工作。

This implementation uses an @Inject annotation. Spring tries to interpret it, interfering with the injection mechanism of the 3rd party library and avoiding it to work as intended.

有没有一种方法可以指导Spring进行操作。实例化bean时,忽略bean实现的 @Inject 批注?

Is there a way to instruct Spring to ignore the @Inject annotations of the bean implementation, when instantiating the bean?

我发现很少有关此主题的问题,但没有一个可以在我的上下文中提供可用的解决方案。

I found few questions about this subject but none of them provided a solution usable in my context.

我实际上通过将第三方对象包装在匿名类中来自己解决了此问题,显然为Spring设置了障碍,并阻止它查看此对象(请参阅下面的第3点),但我认为这是一个丑陋的解决方法。

I actually managed to resolve the issue myself, by wrapping the 3rd party object in an anonymous class, apparently creating a barrier for Spring and preventing it to look into this object (see the point 3. below), but I consider it to be an ugly workaround.

详细信息:

根据OWL API文档, OWLOntologyManager 的创建方式如下:

According to the OWL API documentation, the OWLOntologyManager is to be created like this:

OWLOntologyManagerFactory ontologyManagerFactory = new OWLManager();
OWLOntologyManager owlOntologyManager = ontologyManagerFactory.get();
//... use owlOntologyManager

确实,在我运行的Spring应用程序中。但是,我需要具有 OWLOntologyManagerFactory application 范围以及 OWLOntologyManager 具有 Session 范围。

Indeed, in my Spring application that was working. However, I need to have the OWLOntologyManagerFactory with an application scope and OWLOntologyManager with a Session scope.

所以我将这两个对象声明为Spring @Bean ,并具有适当的范围,并开始收到错误:

So I declared each of these two objects as a Spring @Bean, with an appropriate scope and started to receive an error:


Error创建名称为 scopedTarget.sessionOWLOntologyManager的bean:通过方法 setIRIMappers参数0表示的不满足的依赖关系;嵌套的异常是org.springframework.beans.factory.NoSuchBeanDefinitionException:没有类型为 java.util.Set的合格Bean:应该至少有1个有资格作为自动装配候选的Bean。依赖注释:{}

请参见下面的代码示例。

See below samples of the code.


  1. 功能性代码首次测试,不满足应用程序需求:



@RestController
public class OntologiesController {
    @RequestMapping("ontologies")
    public String manager_loadOntology(
        @RequestParam(value="ontologyIriString") String ontologyIriString
    ) throws OWLOntologyCreationException
    {
        OWLOntologyManagerFactory ontologyManagerFactory = new OWLManager();
        OWLOntologyManager owlOntologyManager = ontologyManagerFactory.get();
        OWLOntology ontology = owlOntologyManager.loadOntology(IRI.create(ontologyIriString));
        return ontology.toString();
    }
}




  1. 非功能代码无法创建具有以上引用的错误的OWLOntologyManager。



@Configuration
public class ApplicationScopeConfig {
    @Bean
    @ApplicationScope
    public OWLOntologyManagerFactory applicationOWLOntologyManagerFactory() {
        return new OWLManager();
    }
}
@Configuration
public class SessionScopeConfig {
    @Autowired
    OWLOntologyManagerFactory applicationOWLOntologyManagerFactory;
    @Bean
    @SessionScope
    public OWLOntologyManager sessionOWLOntologyManager() {
        return applicationOWLOntologyManagerFactory.get();
    }
}
@RestController
public class OntologiesController {
    @Autowired
    private OWLOntologyManager sessionOWLOntologyManager;
    @RequestMapping("ontologies")
    public String manager_loadOntology(
            @RequestParam(value="ontologyIriString") String ontologyIriString
    ) throws OWLOntologyCreationException
    {
        OWLOntology ontology = sessionOWLOntologyManager.loadOntology(IRI.create(ontologyIriString));
        return ontology.toString();
    }
}




  1. 功能代码可以根据需要工作,但很难看,有什么方法可以改进它吗?

在第二点中的代码中如下修改了sessionOWLOntologyManager(),将其包装到一个匿名类中,该类阻止Spring查看真正的owlOntologyManager。

In the code from the point 2 I modified the sessionOWLOntologyManager() as follows, wrapping it to an anonymous class that prevents Spring to look into the real owlOntologyManager.

@Bean
@SessionScope
public OWLOntologyManager sessionOWLOntologyManager() {
    final OWLOntologyManager owlOntologyManager = applicationOWLOntologyManagerFactory.get();
    return new OWLOntologyManager() {
        public void clearOntologies() {
            owlOntologyManager.clearOntologies();
        }
        //additional 400 lines implementing all methods by delegating to owlOntologyManager
        //Apparently that creates a barrier for Spring so it does not conflict with the
        //@Inject annotation in the implementation of the original owlOntologyManager,
        //but in spite of having IDE support to generate this delegation, I consider it
        //as an workaround.
    }
}


推荐答案

As最终证明,这与配置Spring以忽略带注解的依赖项有关@Inject ,所以我认为获得更好答案的机会很低,我会在对自己的回复中发表自己的其他发现。

As it eventually turns out that this is related to Configuring Spring to ignore dependencies annotated with @Inject, so I assume that a chance to get better answers is low and I post my additional findings in a reply to myself.


  1. 负责识别@Inject的类是org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor。根据我对Spring的了解,我无法拦截其行为。相关问题中提到的类SpringBeanAutowiringInterceptor在Spring 5中不存在。

  1. The class responsible for recognizing the @Inject is org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor. With my Spring knowledge I was however not able to intercept its behavior. The class SpringBeanAutowiringInterceptor, mentioned in the related question, does not exist in Spring 5.

现在,我对第3点的解决方案进行了改进。我没有生成许多委托方法(可以由IDE自动完成),而是使用反射使用下面的代码。好处是,如果我有一天要升级OWLAPI库,它将更能抵抗更改。另外,它的行数明显更少。我认为反射的性能可能较低。

For now I go with an improvement to my solution in the point 3. Instead of generating dozens of delegating methods (it can be done automatically by IDE), I go with the code below, using the reflection. The advantage is that it will be more resistant to changes if I should upgrade the OWLAPI library one day. Also it has significantly less lines. I assume that the reflection might be less performant.



@Bean
@SessionScope
public OWLOntologyManager sessionOWLOntologyManager() {

    final OWLOntologyManager owlOntologyManager = applicationOWLOntologyManagerFactory.get();

    //Instead of returning owlOntologyManager directly,
    //the delegating proxy prevents Spring to resolve @Inject annotations
    //in the implementation of owlOntologyManager.

    return (OWLOntologyManager)Proxy.newProxyInstance(
            owlOntologyManager.getClass().getClassLoader(),
            owlOntologyManager.getClass().getInterfaces(),
            (o, method, args) ->
                method.invoke(owlOntologyManager, args)
        );
}

这篇关于由使用@Inject的第3方库实现的Spring Bean与Spring的注入机制冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆