Spring autowired bean for @ Aspect aspect is null

Mam następującą konfigurację sprężynową:

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

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

<aop:aspectj-autoproxy/>

Wtedy mam aspekt:

@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));
    }
}

Ten aspekt działa (mogę trafić breakpoint na afterPoll), ale simpleEmailSender jest null. Niestety nie mogę znaleźć jasnej dokumentacji, dlaczego tak jest. (Dla przypomnienia, mój simpleEmailSender bean istnieje i jest poprawnie podłączony do innych klas) następujące rzeczy mnie mylą:

  1. czy context: component-scan ma odbierać @ Aspect? Jeśli tak, to z pewnością być wiosną zarządzane fasoli, więc autowired powinien działać?
  2. jeśli context: component-scan nie służy do tworzenia aspektów, jak powstaje mój aspekt? Myślałem, że AOP: aspectj-autoproxy po prostu tworzy beanpostprocesor do proxy mojej klasy @ Aspect? Jak to zrobić, jeśli nie jest to fasola wiosenna?

Oczywiście możesz powiedzieć, że nie mam pojęcia, jak rzeczy powinny działać od podstaw.

Author: mogronalol, 2012-03-09

9 answers

Aspekt jest obiektem singletonowym i jest tworzony poza kontenerem Spring. Rozwiązaniem z konfiguracją XML jest użycie fabrycznej metody Springa do pobrania aspektu.

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

W tej konfiguracji aspekt będzie traktowany jak każda inna fasola Wiosenna, a autowirowanie będzie działać normalnie.

Metodę factory należy stosować również na obiektach Enum i innych obiektach bez konstruktora lub obiektów, które są tworzone poza kontenerem Spring.

 31
Author: Espen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-11 20:56:00

Inną opcją jest dodanie @Configurable do swojej klasy aspect zamiast bawić się w XML.

 17
Author: tobiasbayer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-18 07:22:36

Aby Spring Boot używać @Autowired z AspectJ znalazłem następującą metodę. W klasie konfiguracyjnej dodaj swój aspekt:

@Configuration
@ComponentScan("com.kirillch.eqrul")
public class AspectConfig {

    @Bean
    public EmailAspect theAspect() {
        EmailAspect aspect = Aspects.aspectOf(EmailAspect.class);
        return aspect;
    }

}

Następnie możesz z powodzeniem autowireować swoje usługi w swojej klasie aspect:

@Aspect
public class EmailAspect {

    @Autowired
    EmailService emailService;
 8
Author: Kirill Ch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-06 11:06:49

Nie mam 50 rep, aby skomentować pytanie, więc oto kolejna odpowiedź dotycząca @ Jitendra Vispute odpowiedz Oficjalny Doc Wiosny wspomina:

Możesz zarejestrować klasy aspect jako zwykłe fasolki w konfiguracji Spring XML lub automatycznie wykrywać je poprzez skanowanie classpath - tak jak każda inna fasolka zarządzana przez Spring. Należy jednak pamiętać, że adnotacja @ Aspect nie jest wystarczająca do autodetekcji w ścieżce classpath: w tym celu należy dodać osobny @ Adnotacja komponentu (lub alternatywnie niestandardowa adnotacja stereotypu, która kwalifikuje się, zgodnie z zasadami skanera komponentów Springa).Źródło: Wiosna '4.1.7.Release " documentation .

Oznaczałoby to, że dodanie adnotacji @ Component i dodanie @ComponentScan w konfiguracji sprawiłoby, że przykład @ Jitendra Vispute zadziała. W przypadku spring boot AOP sample zadziałało, choć nie zadzierałem z odświeżaniem kontekstu.Spring boot aop próbka :

Zastosowanie :

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);
    }
}

Aplikacja powinna również działać jako zwykła aplikacja Spring Framework z następującymi adnotacjami zamiast @SpringBootApplication:

  • @Configuration
  • @ EnableAspectJAutoProxy
  • @ComponentScan

I adnotacja Configapplicationcontext zamiast SpringApplication.

Serwis :

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;
    }
}

Monitor Aspect :

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);
    }
}
 4
Author: secure_paul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:09:41

Konfiguracja @Autowired tylko z Java config (więc żadna konfiguracja oparta na XML) wymaga trochę dodatkowej pracy niż tylko dodanie @Configuration do klasy, ponieważ wymaga również metody aspectOf.

To, co zadziałało dla mnie, to stworzenie nowej klasy:

@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;
    }
}

A następnie użyj tego w swoim aspekcie w połączeniu z użyciem @ DependsOn @Configured i @Autowired:

@DependsOn("springApplicationContextHolder")
@Configuration
@Aspect
public class SomeAspect {

    @Autowired
    private SomeBean someBean;

    public static SomeAspect aspectOf() {
        return SpringApplicationContextProvider.getApplicationContext().getBean(SomeAspect.class);
    }

@DependsOn jest potrzebny, ponieważ spring nie może określić zależności, ponieważ fasola jest używana statycznie.

 4
Author: Wouter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-29 22:06:23

Ten post na blogu wyjaśnia to bardzo dobrze. Ze względu na fakt, że aspect singleton jest tworzony poza pojemnikiem sprężynowym, należy użyć factory-method= "aspectOf", który jest dostępny dopiero po wpleceniu go przez AspectJ (nie Spring AOP):

Notice factory-method= "aspectOf", który mówi Springowi, aby użył prawdziwego AspectJ (nie Spring AOP ) aspekt tworzenia tej fasoli. Tak, że po aspekt tkany w nim ma metoda "aspectOf".

Tak, że :

No matching factory method found: factory method 'aspectOf ()' - That oznaczałoby to, że aspekt nie został utkany przez AspectJ weaver.

Z mojego doświadczenia z spring 3.1, Jeśli nie używam @Autowired, ale tradycyjnego settera do iniekcji zależności, To dostaje iniekcję i działa zgodnie z oczekiwaniami bez aspektu. Chociaż mam problemy z aspektem singleton... Powoduje to powstanie modelu instancyjnego "perthis". .

 2
Author: lisak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-16 11:14:44

Dodaj @ Component do aspect class i twoje zależności powinny zostać wstrzyknięte automatycznie. and add context:component-scan for package where your aspect is in spring context file.

@Component
@Aspect
public class SomeAspect {
    /* following dependency should get injected */
    @Autowired
    SomeTask someTask;
    /* rest of code */  
}
 1
Author: Jitendra Vispute,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-03 01:09:53

Użyj splatania czasu kompilacji, zobacz przykład wtyczki pod adresem: https://github.com/avner-levy/minimal_spring_hibernate_maven_setup/blob/master/pom.xml

Następująca kombinacja adnotacji i Spring Config działa dla mnie dzięki notatkom powyżej Tobias/Willie / Eric:

Klasa:

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

XML:

<context:spring-configured />
<context:component-scan base-package="com.abc" />
 0
Author: Qiang Li,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-16 00:44:37
@Configurable(autowire = Autowire.BY_TYPE)

Dodaj tę adnotację do swojej klasy Aspectj. Następnie zajmie się nim wiosenny MKOl.

 0
Author: astronuaa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-29 11:02:16