[SPRING] 어쨌든 생성자 인수가 필요한 빈을 @Autowire로 보내려면?
SPRING어쨌든 생성자 인수가 필요한 빈을 @Autowire로 보내려면?
저는 Spring 3.0.5를 사용하고 있으며 가능한 한 @Autowire 주석을 클래스 멤버에게 사용하고 있습니다. autowire에 필요한 콩 중 하나는 생성자에 대한 인수가 필요합니다. Spring 문서를 살펴 봤지만 생성자 인수에 주석을 추가하는 방법에 대한 참조를 찾을 수없는 것 같습니다.
XML에서는 bean 정의의 일부로 사용할 수 있습니다. @Autowire 주석에 대한 비슷한 메커니즘이 있습니까?
전의:
@Component
public class MyConstructorClass{
String var;
public MyConstructorClass( String constrArg ){
this.var = var;
}
...
}
@Service
public class MyBeanService{
@Autowired
MyConstructorClass myConstructorClass;
....
}
이 예제에서는 @Autowire 주석을 사용하여 MyBeanService에서 "constrArg"값을 어떻게 지정합니까? 이 일을 할 수있는 방법이 있습니까?
감사,
에릭
해결법
-
==============================
1.@Value 주석이 필요합니다.
@Value 주석이 필요합니다.
public class SimpleMovieLister { private MovieFinder movieFinder; private String defaultLocale; @Autowired public void configure(MovieFinder movieFinder, @Value("#{ systemProperties['user.region'] }"} String defaultLocale) { this.movieFinder = movieFinder; this.defaultLocale = defaultLocale; } // ... }
참조 : 표현식 언어> 주석 구성
더 명확히하기 위해, 시나리오에서 MybeanService와 MyConstructorClass라는 두 클래스를 다음과 같이 연결합니다.
@Component public class MyBeanService implements BeanService{ @Autowired public MybeanService(MyConstructorClass foo){ // do something with foo } } @Component public class MyConstructorClass{ public MyConstructorClass(@Value("#{some expression here}") String value){ // do something with value } }
업데이트 : MyConstructorClass의 여러 인스턴스가 서로 다른 값을 필요로하는 경우 Qualifier 주석을 사용해야합니다
-
==============================
2.아니, 네가 의미하는 방식이 아니야. MyConstructorClass를 나타내는 bean은 클라이언트 Bean을 필요로하지 않고 구성 가능해야하므로 MyBeanService는 MyConstructorClass가 구성되는 f}에 대해 say를 얻지 못합니다.
아니, 네가 의미하는 방식이 아니야. MyConstructorClass를 나타내는 bean은 클라이언트 Bean을 필요로하지 않고 구성 가능해야하므로 MyBeanService는 MyConstructorClass가 구성되는 f}에 대해 say를 얻지 못합니다.
이것은 autowiring 문제가 아닙니다. 여기에서 문제는 MyConstructorClass가 @Component라는 점을 감안할 때 Spring이 MyConstructorClass를 인스턴스화하는 방법입니다. 구성 요소 검사를 사용하고 있으므로 MyConstructorClass를 명시 적으로 지정하지 않아도됩니다.
@Sean이 말했듯이 여기서 한 가지 대답은 constructor 매개 변수에 @Value를 사용하여 Spring이 시스템 등록 정보 또는 등록 정보 파일에서 생성자 값을 가져 오는 것입니다. 대안은 MyBeanService가 MyConstructorClass를 직접 인스턴스화하는 것이지만, 그렇게하면 MyConstructorClass는 더 이상 Spring bean이 아닙니다.
-
==============================
3.글쎄, 나는 때때로 같은 질문을한다. 필자가 아는 한, 생성자에 동적 매개 변수를 추가하려면이 작업을 수행 할 수 없습니다. 그러나 공장 패턴이 도움이 될 수 있습니다.
글쎄, 나는 때때로 같은 질문을한다. 필자가 아는 한, 생성자에 동적 매개 변수를 추가하려면이 작업을 수행 할 수 없습니다. 그러나 공장 패턴이 도움이 될 수 있습니다.
public interface MyBean { // here be my fancy stuff } public interface MyBeanFactory { public MyBean getMyBean(/* bean parameters */); } @Component public class MyBeanFactoryImpl implements MyBeanFactory { @Autowired WhateverIWantToInject somethingInjected; public MyBean getMyBean(/* params */) { return new MyBeanImpl(/* params */); } private class MyBeanImpl implements MyBean { public MyBeanImpl(/* params */) { // let's do whatever one has to } } } @Component public class MyConsumerClass { @Autowired private MyBeanFactory beanFactory; public void myMethod() { // here one has to prepare the parameters MyBean bean = beanFactory.getMyBean(/* params */); } }
자, MyBean은 그 자체로 봄베이가 아니지만 충분히 가깝습니다. Dependency Injection은 bean 자체가 아닌 factory를 injection하기도하지만, 새로운 MyBean 구현물 위에 새로운 factory를 삽입해야한다.
또한, MyBean은 다른 빈들에 접근 할 수 있습니다 - 공장의 자동 채워진 것들에 접근 할 수 있기 때문입니다.
그리고 분명히 getMyBean 함수에 일부 논리를 추가하려고 할 수도 있습니다. 이는 허용되는 추가 노력이지만, 불행히도 더 좋은 해결책은 없습니다. 문제는 대개 동적 매개 변수가 데이터베이스 나 사용자 상호 작용과 같은 외부 소스에서 온다는 것이므로 정보를 즉시 사용할 수있는 경우에만 중간 실행시에만 해당 Bean을 인스턴스화해야하므로 팩토리가 적절해야합니다 .
-
==============================
4.다음과 같이 구성 요소를 구성 할 수도 있습니다.
다음과 같이 구성 요소를 구성 할 수도 있습니다.
package mypackage; import org.springframework.context.annotation.Configuration; @Configuration public class MyConstructorClassConfig { @Bean public MyConstructorClass myConstructorClass(){ return new myConstructorClass("foobar"); } } }
Bean 어노테이션을 사용하면 반환 된 빈을 BeanFactory에 등록하도록 Spring에 지시한다.
그래서 당신은 당신이 원하는대로 그것을 autowire 수 있습니다.
-
==============================
5.@Autowired 및 @Value를 사용해야합니다. 이 주제에 대한 자세한 내용은이 게시물을 참조하십시오.
@Autowired 및 @Value를 사용해야합니다. 이 주제에 대한 자세한 내용은이 게시물을 참조하십시오.
-
==============================
6.대안으로는 getter와 setter로 가질 수있는 생성자에 매개 변수를 전달하는 대신 @PostConstruct에서 원하는대로 값을 초기화하는 것입니다. 이 경우 Spring은 기본 생성자를 사용하여 빈을 생성 할 것이다. 아래 예가 있습니다.
대안으로는 getter와 setter로 가질 수있는 생성자에 매개 변수를 전달하는 대신 @PostConstruct에서 원하는대로 값을 초기화하는 것입니다. 이 경우 Spring은 기본 생성자를 사용하여 빈을 생성 할 것이다. 아래 예가 있습니다.
@Component public class MyConstructorClass{ String var; public void setVar(String var){ this.var = var; } public void getVar(){ return var; } @PostConstruct public void init(){ setVar("var"); } ... } @Service public class MyBeanService{ //field autowiring @Autowired MyConstructorClass myConstructorClass; .... }
-
==============================
7.대부분의 해답은 상당히 오래된 것이므로 그 당시에는 불가능했을 수도 있지만 가능한 모든 유스 케이스를 만족시키는 해법이 실제로 존재합니다.
대부분의 해답은 상당히 오래된 것이므로 그 당시에는 불가능했을 수도 있지만 가능한 모든 유스 케이스를 만족시키는 해법이 실제로 존재합니다.
그래서 답은 다음과 같습니다.
이러한 문제를 해결하는 솔루션은 ApplicationContext를 사용하여 수동으로 객체를 생성하는 것입니다.
@Component public class MyConstructorClass { String var; public MyConstructorClass() {} public MyConstructorClass(String constrArg) { this.var = var; } } @Service public class MyBeanService implements ApplicationContextAware { private static ApplicationContext applicationContext; MyConstructorClass myConstructorClass; public MyBeanService() { // Creating the object manually MyConstructorClass myObject = new MyConstructorClass("hello world"); // Initializing the object as a Spring component AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory(); factory.autowireBean(myObject); factory.initializeBean(myObject, myObject.getClass().getSimpleName()); } @Override public void setApplicationContext(ApplicationContext context) throws BeansException { applicationContext = context; } }
이는 다음과 같은 이유로 멋진 솔루션입니다.
명심해야 할 점은 인스턴스화하려는 클래스에서 인수를 취하지 않는 (그리고 비어있을 수있는) 생성자가 있어야한다는 것입니다 (또는 필요한 경우 @Autowired 생성자).
-
==============================
8.또 다른 대안으로, 이미 객체의 인스턴스가 생성되어 있고 그것을 @autowired 의존 관계로 추가하여 내부의 모든 @autowired 변수를 초기화하려는 경우 다음과 같이 할 수 있습니다.
또 다른 대안으로, 이미 객체의 인스턴스가 생성되어 있고 그것을 @autowired 의존 관계로 추가하여 내부의 모든 @autowired 변수를 초기화하려는 경우 다음과 같이 할 수 있습니다.
@Autowired private AutowireCapableBeanFactory autowireCapableBeanFactory; public void doStuff() { YourObject obj = new YourObject("Value X", "etc"); autowireCapableBeanFactory.autowireBean(obj); }
from https://stackoverflow.com/questions/6739566/anyway-to-autowire-a-bean-that-requires-constructor-arguments by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring - POST 후에 리디렉션 (유효성 검사 오류가있는 경우에도) (0) | 2018.12.05 |
---|---|
[SPRING] 왜 우리는 봄에 정적 필드를 autowire 수없는거야? (0) | 2018.12.05 |
[SPRING] 스프링 부트, 스프링 데이터 JPA 여러 데이터 소스 포함 (0) | 2018.12.05 |
[SPRING] 범위 '세션'이 현재 스레드에 대해 활성화되어 있지 않습니다. IllegalStateException : 스레드 바인딩 된 요청이 없습니다. (0) | 2018.12.05 |
[SPRING] application.properties 파일의 Spring Boot app에 HikariCP를 어떻게 구성합니까? (0) | 2018.12.05 |