春季5 AOP:未执行建议

时间:2018-07-29 15:51:15

标签: java spring spring-aop

有人可以帮助我了解我在这里缺少什么

  1. 如果我从StudentModuleConfig中删除@EnableAspectJAutoProxy,则代码可以正常工作
  2. 代码也可以正常工作,我使用@EnableAspectJAutoProxy将建议定义为@Before(“ execution(* fi *(..)))”),并且建议有效

@Before(“ execution(* *(..))”)出现问题,不确定原因

  

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

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

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

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

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

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

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

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

例外: 线程“主”中的异常org.springframework.beans.factory.BeanCreationException:创建在com.springpeople.training.assignment.student.StudentModuleConfig中定义的名称为“ getStudentRepositoryBean”的bean时出错:通过工厂方法的Bean实例化失败;嵌套的异常是org.springframework.beans.BeanInstantiationException:无法实例化[com.springpeople.training.assignment.student.repositoy.StudentRepository]:工厂方法'getStudentRepositoryBean'引发了异常;嵌套的异常是org.springframework.beans.factory.BeanCreationException:在com.springpeople.training.assignment.student.StudentModuleConfig中定义的名称为“ getLoggingAspectBean”的bean创建错误:通过工厂方法的Bean实例化失败;嵌套的异常是org.springframework.beans.BeanInstantiationException:无法实例化[com.springpeople.training.assignment.student.aspect.LoggingAspect]:工厂方法'getLoggingAspectBean'抛出了异常;嵌套异常是org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名称为'getLoggingAspectBean'的bean时出错:当前正在创建请求的bean:是否存在不可解析的循环引用?     在org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:590)

由以下原因导致:org.springframework.beans.BeanInstantiationException:无法实例化[com.springpeople.training.assignment.student.repositoy.StudentRepository]:工厂方法'getStudentRepositoryBean'引发了异常;嵌套的异常是org.springframework.beans.factory.BeanCreationException:在com.springpeople.training.assignment.student.StudentModuleConfig中定义的名称为“ getLoggingAspectBean”的bean创建错误:通过工厂方法的Bean实例化失败;嵌套的异常是org.springframework.beans.BeanInstantiationException:无法实例化[com.springpeople.training.assignment.student.aspect.LoggingAspect]:工厂方法'getLoggingAspectBean'抛出了异常;嵌套异常是org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名称为'getLoggingAspectBean'的bean时出错:当前正在创建请求的bean:是否存在不可解析的循环引用?     在org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)

由以下原因引起:org.springframework.beans.factory.BeanCreationException:在com.springpeople.training.assignment.student.StudentModuleConfig中定义的名称为“ getLoggingAspectBean”的bean创建时出错:通过工厂方法的Bean实例化失败;嵌套的异常是org.springframework.beans.BeanInstantiationException:无法实例化[com.springpeople.training.assignment.student.aspect.LoggingAspect]:工厂方法'getLoggingAspectBean'抛出了异常;嵌套异常是org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名称为'getLoggingAspectBean'的bean时出错:当前正在创建请求的bean:是否存在不可解析的循环引用?     在org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:590)

原因:org.springframework.beans.BeanInstantiationException:无法实例化[com.springpeople.training.assignment.student.aspect.LoggingAspect]:工厂方法'getLoggingAspectBean'抛出异常;嵌套异常是org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名称为'getLoggingAspectBean'的bean时出错:当前正在创建请求的bean:是否存在不可解析的循环引用?     在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:是否存在不可解析的循环引用?     在org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:339)     在org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:215)

  

编辑   如果我执行以下操作,则可以使用。.

从StudentModuleConfig中删除了以下内容

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

并在StudentModuleConfig中添加@ComponantScan,如下所示:

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

但是我仍然有一个问题,如果我通过使用@Bean批注将LoggingAspect声明为bean,为什么它不起作用,这不是我们创建容器托管bean的方式

1 个答案:

答案 0 :(得分:0)

避免尝试手动实例化Aspect Bean,让Spring处理其生命周期。因此,您已经发现,删除StudentModuleConfig.getLoggingAspectBean()并将@ComponentScan添加到类中是正确的选择。

不是Spring用户(我只有一个Spring AOP游乐场项目来回答像您这样的问题),我只能推测那里可能会发生什么。但是我认为Spring会以某种方式认为您想创建一个常规的Spring bean,而不知道它是一个Aspect实例,并且由于全局的切入点而试图将该方面应用到它。因此,错误日志中提到的循环引用。请注意,即使一个方面是@Component,例如,方面无法告知自己。