简体   繁体   English

Spring 5 AOP:不执行建议

[英]Spring 5 AOP : Not executing advice

Could someone please help me to understand what am I missing here 有人可以帮我了解我在这里想念的是什么

  1. The code works fine if I remove @EnableAspectJAutoProxy from StudentModuleConfig 如果我从StudentModuleConfig中删除@EnableAspectJAutoProxy,则代码可以正常工作
  2. The code also works fine I define advice as @Before("execution(* fi*(..))") with @EnableAspectJAutoProxy and advice works 该代码也可以正常工作,我通过@EnableAspectJAutoProxy将建议定义为@Before(“ execution(* fi *(..))”)

Problem happens with @Before("execution(* *(..))"), not sure why @Before(“ execution(* *(..))”)发生问题,不确定为什么

Student.java Student.java

package com.springpeople.training.assignment.student.domain;

import java.util.Collection;
import java.util.Collections;

import com.springpeople.training.assignment.course.domain.Course;

public class Student {
    private String name;
    private String surname;
    private Collection<Course> enrolledCourses = Collections.emptyList();
    private String userName;

    public Student() {
    }

    public Student(String name, String surname, String userName, Course... enrolledCourses) {
        super();
        this.name = name;
        this.surname = surname;
        this.userName = userName;
        for (Course course : enrolledCourses) {
            this.enrolledCourses.add(course);
        }
    }

    public Student(String name, String surname, String userName) {
        super();
        this.name = name;
        this.surname = surname;
        this.userName = userName;
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", surname=" + surname + ", enrolledCourses=" + enrolledCourses + ", userName="
                + userName + "]";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public Collection<Course> getEnrolledCourses() {
        return enrolledCourses;
    }

    public void setEnrolledCourses(Collection<Course> enrolledCourses) {
        this.enrolledCourses = enrolledCourses;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

}

StudentRepository StudentRepository

package com.springpeople.training.assignment.student.repositoy;

import java.util.Collection;

import com.springpeople.training.assignment.course.domain.Course;
import com.springpeople.training.assignment.student.domain.Student;

public interface StudentRepository {
    Collection<Student> findAllStudentByCourse(Course course);
}

StudentRepositoryImpl.java StudentRepositoryImpl.java

package com.springpeople.training.assignment.student.repositoy;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

import com.springpeople.training.assignment.course.domain.Course;
import com.springpeople.training.assignment.student.domain.Student;


public class StudentRepositoryImpl implements StudentRepository {

    public StudentRepositoryImpl() {
        System.out.println("StudentRepositoryImpl constructor invoked");
    }

    public void init() {
        System.out.println("StudentRepositoryImpl.init() invoked");
    }

    public void destroy() {
        System.out.println("StudentRepositoryImpl.destroy() invoked");
    }

    @Override
    public Collection<Student> findAllStudentByCourse(Course course) {
        List<Student> students = new ArrayList<>();
        if (Objects.nonNull(course) && "Spring".equals(course.getName())) {
            students.add(new Student("A", "a", "aa"));
            students.add(new Student("B", "b", "bb"));
        }
        return students;
    }

}

StudentService StudentService

package com.springpeople.training.assignment.student.service;

import java.util.Collection;

import com.springpeople.training.assignment.course.domain.Course;
import com.springpeople.training.assignment.student.domain.Student;

public interface StudentService {
    Collection<Student> findAllStudentByCourse(Course course);
}

StudentServiceImpl StudentServiceImpl

package com.springpeople.training.assignment.student.service;

import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;

import com.springpeople.training.assignment.course.domain.Course;
import com.springpeople.training.assignment.student.domain.Student;
import com.springpeople.training.assignment.student.repositoy.StudentRepository;

public class StudentServiceImpl implements StudentService {

    private StudentRepository repository;

    public StudentServiceImpl() {
        System.out.println("StudentServiceImpl constructor invoked");
    }

    public StudentServiceImpl(StudentRepository repository) {
        this.repository = repository;
    }

    public void init() {
        System.out.println("StudentServiceImpl.init() invoked");
    }

    public void destroy() {
        System.out.println("StudentServiceImpl.destroy() invoked");
    }

    @Override
    public Collection<Student> findAllStudentByCourse(Course course) {
        return repository.findAllStudentByCourse(course);
    }

    public void setStudentRepository(StudentRepository studentRepositoryBean) {
        repository = studentRepositoryBean;
    }

}

LoggingAspect LoggingAspect

package com.springpeople.training.assignment.student.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class LoggingAspect {

    @Before("execution(* *(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("LoggingAspect.logBefore(): "+joinPoint.getSignature().getName());
    }

}

StudentModuleConfig.java StudentModuleConfig.java

package com.springpeople.training.assignment.student;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

import com.springpeople.training.assignment.student.aspect.LoggingAspect;
import com.springpeople.training.assignment.student.repositoy.StudentRepository;
import com.springpeople.training.assignment.student.repositoy.StudentRepositoryImpl;
import com.springpeople.training.assignment.student.service.StudentService;
import com.springpeople.training.assignment.student.service.StudentServiceImpl;

@Configuration
@EnableAspectJAutoProxy
public class StudentModuleConfig {

    @Bean
    public StudentRepository getStudentRepositoryBean() {
        return new StudentRepositoryImpl();
    }

    @Bean
    public StudentService getStudentServiceBean() {
        StudentServiceImpl studentServiceImpl = new StudentServiceImpl();
        studentServiceImpl.setStudentRepository(getStudentRepositoryBean());
        return studentServiceImpl;
    }

    @Bean
    public LoggingAspect getLoggingAspectBean() {
        return new LoggingAspect();
    }
}

App2.java App2.java

package com.springpeople.training.assignment;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.springpeople.training.assignment.course.domain.Course;
import com.springpeople.training.assignment.student.StudentModuleConfig;
import com.springpeople.training.assignment.student.service.StudentService;

public class App2 
{
    public static void main( String[] args ) throws InterruptedException
    {
        ApplicationContext container = new AnnotationConfigApplicationContext(StudentModuleConfig.class);
        StudentService service3 = container.getBean(StudentService.class);
        System.out.println(service3.findAllStudentByCourse(new Course("Spring", 12, "advance")));
    }
}

Exception: Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getStudentRepositoryBean' defined in com.springpeople.training.assignment.student.StudentModuleConfig: Bean instantiation via factory method failed; 异常:线程“主”中的异常org.springframework.beans.factory.BeanCreationException:在com.springpeople.training.assignment.student.StudentModuleConfig中定义的名称为“ getStudentRepositoryBean”的bean创建时出错:通过工厂方法的Bean实例化失败; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.springpeople.training.assignment.student.repositoy.StudentRepository]: Factory method 'getStudentRepositoryBean' threw exception; 嵌套的异常是org.springframework.beans.BeanInstantiationException:无法实例化[com.springpeople.training.assignment.student.repositoy.StudentRepository]:工厂方法'getStudentRepositoryBean'引发了异常; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getLoggingAspectBean' defined in com.springpeople.training.assignment.student.StudentModuleConfig: Bean instantiation via factory method failed; 嵌套的异常是org.springframework.beans.factory.BeanCreationException:在com.springpeople.training.assignment.student.StudentModuleConfig中定义的名称为“ getLoggingAspectBean”的bean创建错误:通过工厂方法的Bean实例化失败; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.springpeople.training.assignment.student.aspect.LoggingAspect]: Factory method 'getLoggingAspectBean' threw exception; 嵌套的异常是org.springframework.beans.BeanInstantiationException:无法实例化[com.springpeople.training.assignment.student.aspect.LoggingAspect]:工厂方法'getLoggingAspectBean'抛出了异常; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'getLoggingAspectBean': Requested bean is currently in creation: Is there an unresolvable circular reference? 嵌套异常是org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名称为'getLoggingAspectBean'的bean时出错:当前正在创建请求的bean:是否存在不可解析的循环引用? at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:590) 在org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:590)处

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.springpeople.training.assignment.student.repositoy.StudentRepository]: Factory method 'getStudentRepositoryBean' threw exception; 原因:org.springframework.beans.BeanInstantiationException:无法实例化[com.springpeople.training.assignment.student.repositoy.StudentRepository]:工厂方法'getStudentRepositoryBean'引发了异常; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getLoggingAspectBean' defined in com.springpeople.training.assignment.student.StudentModuleConfig: Bean instantiation via factory method failed; 嵌套的异常是org.springframework.beans.factory.BeanCreationException:在com.springpeople.training.assignment.student.StudentModuleConfig中定义的名称为“ getLoggingAspectBean”的bean创建错误:通过工厂方法的Bean实例化失败; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.springpeople.training.assignment.student.aspect.LoggingAspect]: Factory method 'getLoggingAspectBean' threw exception; 嵌套的异常是org.springframework.beans.BeanInstantiationException:无法实例化[com.springpeople.training.assignment.student.aspect.LoggingAspect]:工厂方法'getLoggingAspectBean'抛出了异常; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'getLoggingAspectBean': Requested bean is currently in creation: Is there an unresolvable circular reference? 嵌套异常是org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名称为'getLoggingAspectBean'的bean时出错:当前正在创建请求的bean:是否存在不可解析的循环引用? at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) 在org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getLoggingAspectBean' defined in com.springpeople.training.assignment.student.StudentModuleConfig: Bean instantiation via factory method failed; 由以下原因引起:org.springframework.beans.factory.BeanCreationException:在com.springpeople.training.assignment.student.StudentModuleConfig中定义的名称为“ getLoggingAspectBean”的bean创建错误:通过工厂方法的Bean实例化失败; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.springpeople.training.assignment.student.aspect.LoggingAspect]: Factory method 'getLoggingAspectBean' threw exception; 嵌套的异常是org.springframework.beans.BeanInstantiationException:无法实例化[com.springpeople.training.assignment.student.aspect.LoggingAspect]:工厂方法'getLoggingAspectBean'抛出了异常; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'getLoggingAspectBean': Requested bean is currently in creation: Is there an unresolvable circular reference? 嵌套异常是org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名称为'getLoggingAspectBean'的bean时出错:当前正在创建请求的bean:是否存在不可解析的循环引用? at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:590) 在org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:590)处

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.springpeople.training.assignment.student.aspect.LoggingAspect]: Factory method 'getLoggingAspectBean' threw exception; 原因:org.springframework.beans.BeanInstantiationException:无法实例化[com.springpeople.training.assignment.student.aspect.LoggingAspect]:工厂方法'getLoggingAspectBean'抛出异常; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'getLoggingAspectBean': Requested bean is currently in creation: Is there an unresolvable circular reference? 嵌套异常是org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名称为'getLoggingAspectBean'的bean时出错:当前正在创建请求的bean:是否存在不可解析的循环引用? at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:582) ... 38 more Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'getLoggingAspectBean': Requested bean is currently in creation: Is there an unresolvable circular reference? 在org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)在org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:582)... 38更多原因: org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名称为'getLoggingAspectBean'的bean时出错:当前正在创建请求的bean:是否存在不可解析的循环引用? at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:339) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:215) 在org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:215)的org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:339)

Edit If I do the following, it works.. 编辑如果我执行以下操作,则它将起作用。

Removed the following from StudentModuleConfig 从StudentModuleConfig中删除了以下内容

@Bean
    public LoggingAspect getLoggingAspectBean() {
        return new LoggingAspect();
    }

And added @ComponantScan in the StudentModuleConfig as follows: 并在StudentModuleConfig中添加了@ComponantScan,如下所示:

@ComponentScan(basePackages= {"com.springpeople.training.assignment.student.aspect"})

But I still have the question why it didn't work if I declare the LoggingAspect as a bean by using @Bean annotation, is this not the way we can create a container managed bean 但是我仍然有一个问题,如果我通过使用@Bean批注将LoggingAspect声明为bean,为什么它不起作用,这不是我们创建容器托管bean的方式吗?

Avoid trying to instantiate the aspect bean manually, let Spring take care of its lifecycle. 避免尝试手动实例化aspect bean,让Spring处理其生命周期。 So to remove StudentModuleConfig.getLoggingAspectBean() and add @ComponentScan to the class instead is the right thing to do, as you already found out. 因此,如您StudentModuleConfig.getLoggingAspectBean() ,删除StudentModuleConfig.getLoggingAspectBean()并将@ComponentScan添加到类中是正确的选择。

Not being a Spring user (I only have a Spring AOP playground project for answering questions like yours), I can only speculate about what might be happening there. 由于不是Spring用户(我只有一个Spring AOP游乐场项目来回答像您这样的问题),所以我只能推测那里可能会发生什么。 But I think that somehow Spring thinks you want to create a regular Spring bean, not knowing that it is an aspect instance, and tries to apply the aspect to it because of your global catch-all pointcut. 但是我认为Spring会以某种方式认为您想创建一个常规的Spring bean,而不知道它是一个Aspect实例,并且由于全局的切入点而试图将该方面应用到它。 Thus the mentioned circular reference in the error log. 因此,错误日志中提到的循环引用。 Note that an aspect is not a normal bean even though it is a @Component , eg aspects cannot advise themselves. 请注意,即使一个方面是@Component ,它也不是普通的bean,例如,方面无法自我建议。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM