복붙노트

[SPRING] @Aspect aspect에 대한 스프링 autowired bean은 null이다.

SPRING

@Aspect aspect에 대한 스프링 autowired bean은 null이다.

나는 다음과 같은 스프링 구성을 가지고있다 :

<context:component-scan base-package="uk.co.mysite.googlecontactsync.aop"/>

<bean name="simpleEmailSender" class="uk.co.mysite.util.email.simple.SimpleEmailSenderImplementation"/>

<aop:aspectj-autoproxy/>

그럼 나는 측면이있다 :

@Aspect
public class SyncLoggingAspect {
    @Autowired
    private SimpleEmailSender simpleEmailSender

    @AfterReturning(value="execution(* uk.co.mysite.datasync.polling.Poller+.doPoll())", returning="pusher")
    public void afterPoll(Pusher pusher) {      
        simpleEmailSender.send(new PusherEmail(pusher));
    }
}

이 aspect는 작동한다 (나는 afterPoll에서 breakpoint를 칠 수있다). 그러나 simpleEmailSender는 null이다. 불행히도 이것이 왜 그런지에 대한 명확한 문서를 찾을 수 없습니다. (기록을 위해, 내 simpleEmailSender 빈이 존재하고 다른 클래스에 올바르게 연결되어 있습니다) 다음과 같은 것들이 나를 혼란스럽게합니다 :

분명히 당신은 내가 일들이 처음부터 어떻게 작동해야 하는지를 이해하지 못한다고 말할 수 있습니다.

해결법

  1. ==============================

    1.애스펙트는 싱글 톤 객체이며 Spring 컨테이너 외부에서 생성된다. XML 설정의 솔루션은 Spring의 factory 메소드를 사용하여 aspect를 가져 오는 것이다.

    애스펙트는 싱글 톤 객체이며 Spring 컨테이너 외부에서 생성된다. XML 설정의 솔루션은 Spring의 factory 메소드를 사용하여 aspect를 가져 오는 것이다.

    <bean id="syncLoggingAspect" class="uk.co.demo.SyncLoggingAspect" 
         factory-method="aspectOf" />
    

    이 구성으로 aspect는 다른 Spring bean처럼 취급 될 것이고 autowiring은 정상적으로 작동 할 것이다.

    Spring 컨테이너 외부에서 생성 된 생성자 또는 객체없이 Enum 객체 및 기타 객체에도 factory 메소드를 사용해야합니다.

  2. ==============================

    2.또 다른 옵션은 @Configurable을 XML로 어지럽히 지 않고 aspect 클래스에 추가하는 것입니다.

    또 다른 옵션은 @Configurable을 XML로 어지럽히 지 않고 aspect 클래스에 추가하는 것입니다.

  3. ==============================

    3.Spring Boot가 @Autowired와 AspectJ를 사용하기 위해서 나는 다음과 같은 방법을 발견했다. 구성 클래스에서 다음과 같이 추가하십시오.

    Spring Boot가 @Autowired와 AspectJ를 사용하기 위해서 나는 다음과 같은 방법을 발견했다. 구성 클래스에서 다음과 같이 추가하십시오.

    @Configuration
    @ComponentScan("com.kirillch.eqrul")
    public class AspectConfig {
    
        @Bean
        public EmailAspect theAspect() {
            EmailAspect aspect = Aspects.aspectOf(EmailAspect.class);
            return aspect;
        }
    
    }
    

    그런 다음 aspect 클래스에서 서비스를 성공적으로 autowire 할 수 있습니다.

    @Aspect
    public class EmailAspect {
    
        @Autowired
        EmailService emailService;
    
  4. ==============================

    4.나는 질문에 대하여 논평 할 50 명의 담당자가 없기 때문에 여기에 관한 또 다른 대답은 @ Jitendra Vispute 대답. 공식적인 스프링 박사는 언급 :

    나는 질문에 대하여 논평 할 50 명의 담당자가 없기 때문에 여기에 관한 또 다른 대답은 @ Jitendra Vispute 대답. 공식적인 스프링 박사는 언급 :

    즉, @Component 주석을 추가하고 @ComponentScan을 구성에 추가하면 @Jitendra Vispute의 예제가 작동합니다. 봄 부팅 aop 샘플 들어, 비록 내가 컨텍스트 refreshing.Spring 부팅 aop 샘플 주위에 난장판 않았어 ​​일했다 :

    신청:

    package sample.aop;
    @SpringBootApplication
    public class SampleAopApplication implements CommandLineRunner {
        // Simple example shows how an application can spy on itself with AOP
        @Autowired
        private HelloWorldService helloWorldService;
        @Override
        public void run(String... args) {
            System.out.println(this.helloWorldService.getHelloMessage());
        }
        public static void main(String[] args) throws Exception {
            SpringApplication.run(SampleAopApplication.class, args);
        }
    }
    

    @SpringBootApplication 대신 다음 주석이있는 일반 Spring Framework 응용 프로그램으로도 실행해야합니다.

    SpringApplication 대신 AnnotationConfigApplicationContext를 사용한다.

    서비스:

    package sample.aop.service;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    @Component
    public class HelloWorldService {
        @Value("${name:World}")
        private String name;
        public String getHelloMessage() {
            return "Hello " + this.name;
        }
    }
    

    모니터 화면 :

    package sample.aop.monitor;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.stereotype.Component;
    @Aspect
    @Component
    public class ServiceMonitor {
        @AfterReturning("execution(* sample..*Service.*(..))")
        public void logServiceAccess(JoinPoint joinPoint) {
            System.out.println("Completed: " + joinPoint);
        }
    }
    
  5. ==============================

    5.Java 구성만으로 @Autowired를 구성하면 (XML 기반 구성이 필요하지 않음) aspectOf 메소드가 필요하므로 @Configuration을 클래스에 추가하는 것보다 약간의 추가 작업이 필요합니다.

    Java 구성만으로 @Autowired를 구성하면 (XML 기반 구성이 필요하지 않음) aspectOf 메소드가 필요하므로 @Configuration을 클래스에 추가하는 것보다 약간의 추가 작업이 필요합니다.

    나에게 도움이 된 것은 새로운 수업을 만드는 것이었다.

    @Component
    public class SpringApplicationContextHolder implements ApplicationContextAware {
    
        private static ApplicationContext applicationContext = null;
    
        public static ApplicationContext getApplicationContext() {
            return applicationContext;
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
           this.applicationContext = applicationContext;
        }
    }
    

    그리고 @DependsOn @Configured와 @Autowired를 함께 사용하여 여러분의 측면에서 그것을 사용하십시오 :

    @DependsOn("springApplicationContextHolder")
    @Configuration
    @Aspect
    public class SomeAspect {
    
        @Autowired
        private SomeBean someBean;
    
        public static SomeAspect aspectOf() {
            return SpringApplicationContextProvider.getApplicationContext().getBean(SomeAspect.class);
        }
    

    @DependsOn은 bean이 정적으로 사용되기 때문에 Spring이 의존성을 결정할 수 없기 때문에 필요합니다.

  6. ==============================

    6.이 블로그 게시물은 정말 잘 설명합니다. 애스펙트 싱글 톤은 스프링 컨테이너 외부에서 생성되기 때문에 factory-method = "aspectOf"를 사용해야합니다. AspectJ (AOP가 아닌 AspectJ)가 짜 넣은 후에 만 ​​사용할 수 있습니다.

    이 블로그 게시물은 정말 잘 설명합니다. 애스펙트 싱글 톤은 스프링 컨테이너 외부에서 생성되기 때문에 factory-method = "aspectOf"를 사용해야합니다. AspectJ (AOP가 아닌 AspectJ)가 짜 넣은 후에 만 ​​사용할 수 있습니다.

    그렇게 :

    Spring 3.1에 대한 나의 경험에서 @Autowired 그러나 전통적인 setter를 의존성 삽입에 사용하지 않으면 aspectJ 위버없이 주입되고 예상대로 작동한다. 싱글 톤이라는 측면에서 문제가 발생하지만 ... 'perthis'인스턴스화 모델이됩니다. .

  7. ==============================

    7.애스펙트 클래스에 @Component를 추가하면 종속성이 자동으로 주입됩니다. 컨텍스트 추가 : 컨텍스트가 스프링 컨텍스트 파일에있는 패키지의 구성 요소 스캔.

    애스펙트 클래스에 @Component를 추가하면 종속성이 자동으로 주입됩니다. 컨텍스트 추가 : 컨텍스트가 스프링 컨텍스트 파일에있는 패키지의 구성 요소 스캔.

    @Component
    @Aspect
    public class SomeAspect {
        /* following dependency should get injected */
        @Autowired
        SomeTask someTask;
        /* rest of code */  
    }
    
  8. ==============================

    8.컴파일 시간 짜기를 사용합니다. 플러그인 예제는 https://github.com/avner-levy/minimal_spring_hibernate_maven_setup/blob/master/pom.xml에서 참조하십시오.

    컴파일 시간 짜기를 사용합니다. 플러그인 예제는 https://github.com/avner-levy/minimal_spring_hibernate_maven_setup/blob/master/pom.xml에서 참조하십시오.

    Tobias / Willie / Eric이 작성한 주석에 감사드립니다.

    수업:

    package com.abc
    @Configurable
    @Aspect
    public class MyAspect {
       @Autowired
       protected SomeType someAutoWiredField;
    }
    

    XML :

    <context:spring-configured />
    <context:component-scan base-package="com.abc" />
    
  9. ==============================

    9.

    @Configurable(autowire = Autowire.BY_TYPE)
    

    이 주석을 Aspectj 클래스에 추가하십시오. 그런 다음 Spring IOC에 의해 처리 될 것입니다.

  10. from https://stackoverflow.com/questions/9633840/spring-autowired-bean-for-aspect-aspect-is-null by cc-by-sa and MIT license