无论如何@ Inject / @将内部类自动装入一个外部类?

在Spring / JSR-330中,有没有办法正确声明需要dependency injection的内部类,这样我可以将它注入外部类?

例如:

@Component public class TestClass{ // How to declare this class? private class TestClassInner{ @Autowired private SomeBean somebean; public boolean doSomeWork(){ return somebean.doSomething(); } } // Inject the inner class here in the outer class such that the outer class can use an instance of it @Autowired TestClassInner innerClass; @PostConstruct public void init(){ ... } public void someMethod(){ innerClass.doSomeWork(); ... } } 

我尝试使用@Component注释内部类,使其成为公共类,使其成为公共静态等,但似乎我尝试的每个组合总是会抛出一个或另一个错误。

作为一个私有内部类,Spring抱怨它缺少一个构造函数,即使我定义了一个。

作为一个带注释的@Component公共静态类,Spring抱怨它找到了两个bean – TestClass @ TestClassInner和testClass.TestClassInner。 如果我使用@Qualifier ,它会抱怨无法找到bean。

我认为我误解了这些内部bean如何工作/与Spring交互以正确理解是否/如何声明它们。

这有可能吗?

编辑

所以这里有一些我尝试过的组合(包括尝试实现基于@SotiriosDelimanolis响应的新构造函数):

  // How to declare this class? @Component public class TestClassInner{ @Autowired private ProviderService providerService; public TestClassInner(){ super(); } public TestClassInner( TestClass t){ super(); } } 

引发错误(公共和私有内部类都抛出相同的错误):

 Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.ia.exception.TestClass$TestClassInner]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.ia.exception.TestClass$TestClassInner.() at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:83) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1030) ... 54 more 

我只是尝试使用我的测试类(上面)的静态公共嵌套类,它似乎正确注入。 另一方面,在我的实际控制器中,它发现了2个匹配的类:

 Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.ia.web.ContractController$InnerClass] is defined: expected single matching bean but found 2: com.ia.web.ContractController$InnerClass,contractController.InnerClass at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:865) 

编辑2

 @Controller public class ContractController { @Component static public class InnerClass extends AttachmentControllerSupport{ /** * */ public InnerClass() { super(); // TODO Auto-generated constructor stub } public InnerClass( ContractController c){ super(); } } @Autowired private InnerClass innerclass; @Autowired private AttachmentControllerSupport attachmentControllerSupport; @Autowired private ContractService contractService; } 

applicationContext.xml中:

      

restmvc-config.xml文件:

      

可以通过@Component注释声明和实例化内部类bean,但解决方案很难看,但我稍后会介绍它。 首先,这里是如何使用XML中的声明来完成的。 特定

 package com.example; public class Example { @Autowired private Inner inner; public class Inner { } } 

你有

     

对于内部类,任何构造函数都隐式声明其第一个参数作为封闭类型的实例。

所以

 public Inner() {} 

以上将实际编译为

 public Inner (Example enclosingInstance) {} 

使用Java代码时,该参数的参数将隐式提供语法

 enclosingInstance.new Inner(); 

Spring使用reflection来实例化bean类并初始化bean。 这里描述的概念也适用于反思。 用于初始化Inner类的Constructor函数必须使其第一个参数属于封闭类的类型。 通过声明constructor-arg这就是我们在这里明确做的。

使用@Component的解决方案取决于一些事情。 首先,你必须知道上面讨论的所有事情。 基本上,使用Constructor对象时,在调用newInstance() ,需要将封闭类的实例作为第一个参数传递。 其次,您必须知道Spring如何处理注释。 当带注释的类有一个用@Autowired注释的构造函数时,它将选择初始化bean的构造函数。 它还使用ApplicationContext来解析bean作为参数注入构造函数。

利用这两个事实,你可以写一个这样的课程

 @Component public class Example { @Component public class Inner { @Autowired public Inner() {} } } 

这里,我们的内部类有一个@Autowired构造函数,因此Spring确切地知道要使用哪个Constructor对象。 由于@Autowired它还将尝试从ApplicationContext查找一个bean,以匹配和注入构造函数所具有的每个参数。 在这种情况下,唯一的参数是Example类型,封闭类。 由于Example也使用@Component注释,因此它也是上下文中的bean,因此Spring可以将它注入内部类的构造函数中。