使用Spring Boot的AOP

Moh*_*nan 3 spring-aop spring-boot

我在STS的Spring Boot启动项目中使用了这个Spring AOP代码.经过一段时间的调试后,我发现AspectJ语法没有任何问题.Maven依赖关系是由STS为AOP启动项目生成的.这个代码中有一个明显的遗漏,就像注释一样吗?另一个问题可能是AOP启动项目或我尝试在@PostConstruct方法中测试代码的方式.

我安装了AJDT,但似乎STS应该在IDE中自己显示AspectJ标记.对 ?我没有看到标记.STS中包含哪些其他AspectJ调试选项?-Xlint是我在Eclipse/AJDT中使用的.

StateHandler.java

public class StateHandler<EVENTTYPE extends EventType> {


private State<EVENTTYPE> state;

private Event<EVENTTYPE> event;

public StateHandler(State<EVENTTYPE> state, Event<EVENTTYPE> event) {
    this.state = state;
    this.event = event;
}


public void handle( Event<EVENTTYPE> event ){

    state = state.handle( event );

}

public State<EVENTTYPE> getState() {
    return state;
}

}
Run Code Online (Sandbox Code Playgroud)

DeviceLogger .java

    @Aspect
    @Component
    public class DeviceLogger {

    private static Logger logger = Logger.getLogger("Device");


        @Around("execution(* com.devicemachine.StateHandler.*(..))")
        public void log() {
            logger.info( "Logger" );
        }
}
Run Code Online (Sandbox Code Playgroud)

LoggerApplication.java

@SpringBootApplication
public class LoggerApplication {

    private static Logger logger = Logger.getLogger("Device");


    public static void main(String[] args) {

        SpringApplication.run(LoggerApplication.class, args);

    }

    @PostConstruct
    public void log(){
        DeviceState s = DeviceState.BLOCKED;
        StateHandler<DeviceEvent> sh = new StateHandler<DeviceEvent>( s,
                                            Event.block(DeviceEvent.BLOCKED, "AuditMessage") );
        sh.handle(Event.block(DeviceEvent.UNBLOCKED, "AuditMessage"));
    }
}
Run Code Online (Sandbox Code Playgroud)

M. *_*num 10

有3个明显的错误,1个不那么明显的错误.

  1. 您的方面是错误的,并破坏正确的方法执行.使用around方面时,您必须始终返回Object并使用a ProceedingJoinPoint并调用proceed()它.
  2. 您自己正在创建类的新实例,默认情况下,Spring使用基于代理的AOP,并且只会代理它知道的bean.
  3. 在一种@PostConstruct方法中,可能尚未创建代理并且没有任何内容被截获
  4. 您需要使用基于类的代理才能启用添加spring.aop.proxy-target-class=true到您的代理application.properties.默认情况下,使用基于接口的JDK动态代理.

修复方面

您当前的方面不使用a ProceedingJoinPoint,因此从不进行实际的方法调用.接下来,如果您现在有一个返回值的方法,它会突然返回null.因为你没有打电话proceedProceedingJoinPoint.

@Around("execution(* com.devicemachine.StateHandler.*(..))")
public Object log(ProceedingJoinPoint pjp) throws Throwable {
    logger.info( "Logger" );
    return pjp.proceed();
}
Run Code Online (Sandbox Code Playgroud)

创建一个bean来修复代理和 @PostConstruct

@SpringBootApplication
public class LoggerApplication {

    private static Logger logger = Logger.getLogger("Device");

    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(LoggerApplication.class, args);
        StateHandler<DeviceEvent> sh = context.getBean(StateHandler<DeviceEvent>.class);
        sh.handle(Event.block(DeviceEvent.UNBLOCKED, "AuditMessage"));
    }

    @Bean
    public StateHandler<DeviceEvent> auditMessageStateHandler() {
        return new StateHandler<DeviceEvent>(DeviceState.BLOCKED, Event.block(DeviceEvent.BLOCKED, "AuditMessage") );
    }

}
Run Code Online (Sandbox Code Playgroud)

添加属性以启用类代理

在你的application.propertiesin中src\main\resources添加值为的以下属性true

spring.aop.proxy-target-class=true
Run Code Online (Sandbox Code Playgroud)