Nice programing

스프링 자체 주입

nicepro 2020. 12. 12. 12:28
반응형

스프링 자체 주입


나는 실패한 Spring 3.x로 다음 코드를 시도했고 BeanNotFoundException내가 전에 물었던 질문에 대한 대답에 따라야합니다-Spring을 사용하여 동일한 클래스를 주입 할 수 있습니까?

@Service
public class UserService implements Service{
    @Autowired
    private Service self;
}

Java 6에서 이것을 시도했기 때문에 다음 코드가 제대로 작동한다는 것을 알았습니다.

@Service(value = "someService")
public class UserService implements Service{
    @Resource(name = "someService")
    private Service self;
}

하지만 순환 종속성을 해결하는 방법을 이해하지 못합니다.

편집 :
여기에 오류 메시지가 있습니다. OP는 답변 중 하나에 대한 의견에서 언급했습니다.

원인 : org.springframework.beans.factory.NoSuchBeanDefinitionException : 종속성에 대해 일치하는 [com.spring.service.Service] 유형의 Bean이 없습니다.이 종속성에 대한 자동 연결 후보로 자격을 갖춘 하나 이상의 Bean이 필요합니다. 종속성 주석 : {@ org.springframework.beans.factory.annotation.Autowired (required = true)}


업데이트 : 2016 년 2 월

자체 자동 연결 은 Spring Framework 4.3에서 공식적으로 지원됩니다. 구현은이 GitHub commit 에서 볼 수 있습니다 .


스스로 자동 배선 할 수없는 결정적인 이유는 Spring의 DefaultListableBeanFactory.findAutowireCandidates(String, Class, DependencyDescriptor)메소드 구현 이 가능성을 명시 적으로 배제하기 때문입니다. 이 메서드에서 발췌 한 다음 코드에서 볼 수 있습니다.

for (String candidateName : candidateNames) {
    if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, descriptor)) {
        result.put(candidateName, getBean(candidateName));
    }
}

참고 : 빈 (즉, 자동 연결을 시도하는 빈)의 이름은 beanName입니다. 그 빈은 사실 autowire 후보이지만 위의 if-condition은 false를 반환합니다 ( candidateName실제로는 beanName). 따라서 당신은 그 자체로 빈을 autowire 할 수 없다 (적어도 Spring 3.1 M1에서는 아니다).

이것이 의미 론적으로 말해서 의도 된 행동인지 아닌지는 또 다른 질문입니다. ;)

나는 Juergen에게 물어보고 그가 무엇을 말해야하는지 볼 것입니다.

문안 인사,

Sam (코어 스프링 커미터)

추신 @Autowired를 사용하여 유형별로 자체 자동 연결을 지원하는 것을 고려하기 위해 Spring JIRA 문제를 열었습니다. https://jira.springsource.org/browse/SPR-8450 에서이 문제를 보거나 투표하십시오.


이 코드도 작동합니다.

@Service
public class UserService implements Service {

    @Autowired
    private ApplicationContext applicationContext;

    private Service self;

    @PostConstruct
    private void init() {
        self = applicationContext.getBean(UserService.class);
    }
}

이유는 모르겠지만 Spring이 ApplicationContextif is created 에서 bean을 가져올 수 있지만 초기화 되지 않은 것 같습니다 . @Autowired초기화 전에 작동하며 동일한 빈을 찾을 수 없습니다. 그래서, @Resource어쩌면 한 후 작동 @Autowired및 이전 @PostConstruct.

그러나 나는 단지 추측 만하고있다. 어쨌든 좋은 질문입니다.


By the way, the more elegant solution to the self-invocation problem is to use AspectJ Load-Time Weaving for your transactional proxies (or whatever AOP-introduced proxy you're using).

For example, with annotation-driven transaction management, you can use the "aspectj" mode as follows:

<tx:annotation-driven mode="aspectj" />

Note that the default mode is "proxy" (i.e., JDK dynamic proxies).

Regards,

Sam


Given above code I don't see a cyclic dependency. You injecting some instance of Service into UserService. The implementation of the injected Service does not necessarily need to be another UserService so there is no cyclic dependency.

I do not see why you would inject a UserService into UserService but I'm hoping this is a theoretic try out or such.


Get AOP proxy from the object itself question suggests alternative hacky approach with AopContext.currentProxy() that may be suitable for special cases.


It looks like spring creates and configures an object and then places it in the bean look up context. But, in the case of Java, I think it creates the object and ties it to the name and the during configuration when the object is looked up by the name it is found in the context.


Just another aproach:

@EnableAsync
@SpringBootApplication
public class Application {

    @Autowired
    private AccountStatusService accountStatusService;

    @PostConstruct
    private void init() {
        accountStatusService.setSelf(accountStatusService);
    }
}

@Service
public class AccountStatusService {
    private AccountStatusService self;

    public void setSelf(AccountStatusService self) {
        this.self = self;
    }
}

with this your service will be in proxy. I did this to work with async methods inside itself.

I have tryied @sinuhepop solution:

@PostConstruct
private void init() {
    self = applicationContext.getBean(UserService.class);
}

It did a injection but the service wasn't inside proxy and my methods wasn't running on a new thread. With that aproach it works as i would like.

참고URL : https://stackoverflow.com/questions/5152686/self-injection-with-spring

반응형