[SPRING] 어쨌든 @ Inject / @ Autowire로 내부 클래스를 외부 클래스에 넣으시겠습니까?
SPRING어쨌든 @ Inject / @ Autowire로 내부 클래스를 외부 클래스에 넣으시겠습니까?
Spring / JSR-330에는 종속 클래스 삽입이 필요한 내부 클래스를 올바르게 선언 할 수있는 방법이 있습니까? 예를 들어 외부 클래스에 삽입 할 수 있습니까?
예 :
@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 주석을 달고 public 클래스로 만들고 public static으로 만들려고 시도했지만, 시도한 모든 조합은 항상 하나의 에러 또는 다른 것을 던지는 것으로 끝난다.
개인적인 내부 클래스 인 Spring은 생성자를 정의하더라도 생성자가 누락되었다고 불평합니다.
주석이있는 @Component public static 클래스 인 Spring은 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();
}
}
오류를 throw합니다 (public 및 private 내부 클래스 모두 동일한 오류가 발생 함).
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.<init>()
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 :
<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/>
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>
해결법
-
==============================
1.@Component 주석을 통해 내부 클래스 bean을 선언하고 인스턴스화하는 것은 가능하지만 솔루션은 추악하다.하지만 나중에 설명하겠다. 먼저 XML에서
선언을 사용하여이를 수행 할 수 있습니다. 주어진 @Component 주석을 통해 내부 클래스 bean을 선언하고 인스턴스화하는 것은 가능하지만 솔루션은 추악하다.하지만 나중에 설명하겠다. 먼저 XML에서
선언을 사용하여이를 수행 할 수 있습니다. 주어진 package com.example; public class Example { @Autowired private Inner inner; public class Inner { } }
너는 가질거야.
<bean name="ex" class="com.example.Example" /> <bean name="inner" class="com.example.Example$Inner"> <constructor-arg ref="ex"></constructor-arg> </bean>
내부 클래스의 경우 모든 생성자가 암시 적으로 첫 번째 매개 변수를 둘러싸는 유형의 인스턴스로 선언합니다.
그래서
public Inner() {}
위의 내용은 실제로 컴파일 될 것입니다.
public Inner (Example enclosingInstance) {}
Java 코드를 사용하면 해당 매개 변수에 대한 인수에 내재적으로 구문이 제공됩니다
enclosingInstance.new Inner();
Spring은 리플렉션을 사용하여 Bean 클래스를 인스턴스화하고 Bean을 초기화한다. 여기에 설명 된 개념은 리플렉션에도 적용됩니다. Inner 클래스를 초기화하는 데 사용되는 생성자는 첫 번째 매개 변수를 둘러싸는 클래스 유형으로 지정해야합니다. 이것이 constructor-arg를 선언함으로써 명시 적으로 여기에서 수행하는 작업입니다.
@Component를 사용하는 솔루션은 몇 가지 사항에 달려 있습니다. 첫째, 위에서 언급 한 모든 것을 알아야합니다. 기본적으로 Constructor 객체를 사용하여 newInstance ()를 호출하면 둘러싸는 클래스의 인스턴스를 첫 번째 인수로 전달해야합니다. 둘째, Spring이 어노테이션을 어떻게 처리 하는지를 알아야한다. 주석이 달린 클래스에 @Autowired로 주석 처리 된 단일 생성자가있는 경우 생성자가 Bean을 초기화하도록 선택합니다. 또한 ApplicationContext를 사용하여 Bean을 생성자에 인수로 삽입합니다.
이 두 가지 사실을 실행하면 다음과 같은 클래스를 작성할 수 있습니다.
@Component public class Example { @Component public class Inner { @Autowired public Inner() {} } }
여기, 우리 내부 클래스에는 @Autowired 생성자가 있으므로 Spring은 사용할 생성자 객체를 정확히 알고 있습니다. @Autowired 때문에, ApplicationContext로부터 bean을 찾아서 생성자가 가진 모든 매개 변수에 일치시키고 삽입하려고 시도 할 것이다. 이 경우 유일한 매개 변수는 둘러싼 클래스 인 Example입니다. Example 또한 @Component로 주석 처리되었으므로 컨텍스트의 Bean이기도하므로 Spring은 내부 클래스의 생성자에이를 삽입 할 수 있습니다.
from https://stackoverflow.com/questions/24213823/anyway-to-inject-autowire-an-inner-class-into-an-outer-class by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] JPA2 Criteria-API : select ... in (어디에서 선택 하시겠습니까?) (0) | 2019.02.12 |
---|---|
[SPRING] 클라이언트 비밀없이 Spring OAuth2 서버로부터 access_token을 얻을 수 있습니까? (0) | 2019.02.12 |
[SPRING] spring-3.1로 업그레이드하면 내 사용자 정의 WebArgumentResolver가 손상되는 것 같습니다. (0) | 2019.02.12 |
[SPRING] @ResponseBody 주석을 사용할 때의 빈 문자열로서의 널 값 (0) | 2019.02.12 |
[SPRING] Maven 인덱스 재구성 0 %에서 멈춤 (0) | 2019.02.12 |