Java 是否要将内部类@Inject/@Autowire连接到外部类?
在Spring/JSR-330中,有没有一种方法可以正确地声明一个需要依赖注入的内部类,这样我就可以将它注入到外部类中Java 是否要将内部类@Inject/@Autowire连接到外部类?,java,spring,dependency-injection,Java,Spring,Dependency Injection,在Spring/JSR-330中,有没有一种方法可以正确地声明一个需要依赖注入的内部类,这样我就可以将它注入到外部类中 <mvc:annotation-driven conversion-service="applicationConversionService" > <mvc:argument-resolvers> <bean class="org.springframework.security.web.bind.support.Authentica
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
例如:
@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();
...
}
}
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
我尝试过用@Component注释内部类,使其成为公共类,使其成为公共静态类,等等,但似乎我尝试过的每一个组合最终都会抛出一个或另一个错误
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
作为一个私有内部类,Spring抱怨它缺少构造函数,即使我定义了一个构造函数
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
作为一个带注释的@组件
公共静态类,Spring抱怨它发现了两个bean-TestClass@TestClassInner和testClass.TestClassInner。如果我使用@限定符
,它就会抱怨找不到bean
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
我想我误解了这些内部bean如何工作/与Spring交互,从而正确理解是否/如何声明它们
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
这可能吗
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
编辑
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
下面是我尝试过的几个组合(包括尝试基于@SotiriosDelimanolis响应实现一个新的构造函数):
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
抛出错误(公共和私有内部类都抛出相同的错误):
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
编辑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;
}
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
applicationContext.xml:
<context:component-scan base-package="com.ia">
<context:exclude-filter expression=".*_Roo_.*" type="regex"/>
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
<context:spring-configured/>
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
restmvc-config.xml:
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
可以通过
@Component
注释声明和实例化内部类bean,但解决方案很难看,但我稍后会讨论。首先,这里介绍如何使用XML中的
声明。给定
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
package com.example;
public class Example {
@Autowired
private Inner inner;
public class Inner {
}
}
你会的
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
<bean name="ex" class="com.example.Example" />
<bean name="inner" class="com.example.Example$Inner">
<constructor-arg ref="ex"></constructor-arg>
</bean>
上述内容实际上将被编译为
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
public Inner (Example enclosingInstance) {}
对于Java代码,该参数的参数隐式地与语法一起提供
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
enclosingInstance.new Inner();
Spring使用反射来实例化bean类并初始化bean。这里描述的概念也适用于反射。用于初始化内部
类的构造函数
的第一个参数必须是封闭类的类型。这就是我们在这里通过声明一个构造函数arg
明确地做的事情
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
使用@组件的解决方案取决于以下几点。首先,你必须知道上面讨论的所有事情。基本上,对于构造函数
对象,当调用newInstance()
时,需要传递封闭类的实例作为第一个参数。其次,您必须知道Spring如何处理注释。当被注释的类有一个用@Autowired
注释的构造函数时,它将选择该构造函数来初始化bean。它还使用ApplicationContext
解析要作为参数注入构造函数的bean
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
根据这两个事实,您可以编写这样的类
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
@Component
public class Example {
@Component
public class Inner {
@Autowired
public Inner() {}
}
}
在这里,我们的内部类有一个@Autowired
构造函数,因此Spring确切地知道要使用哪个构造函数。由于@Autowired
的原因,它还将尝试从ApplicationContext
中找到一个bean,以匹配并注入构造函数具有的每个参数。在本例中,唯一的参数类型为Example
,即封闭类。由于示例
也用@Component
注释,因此它也是上下文中的一个bean,因此Spring可以将它注入到内部类的构造函数中。答案看起来很有趣。我肯定地知道@Configuration
可以做到这一点,如果这是特定于构造型的,我会感到惊讶。@chrylisby@Configuration
你是说用@Bean
方法显式创建一个内部类instance吗?对不起,我不太清楚。我的意思是,我经常使用带有@Configuration
注释的嵌套(但静态,而不是内部)类,没有任何问题。@chrylis这就是嵌套(静态)与内部的全部区别。嵌套类只是普通类。内部类引用了一个封闭的实例。对于初学者来说,您不正确的术语混淆了一个本身就足够复杂的问题。在Java中,“内部类”是一个非静态嵌套类;嵌套类可以是内部的,也可以是静态的。@chrylis我实际上没有意识到这一点。谢谢你的澄清。我在这里使用术语“内部类”来指嵌套类。我会试着在编辑这篇文章时牢记这一点
<mvc:annotation-driven conversion-service="applicationConversionService" >
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>