AOP 使用 Spring 启动

AOP using Spring Boot

我在我的 Spring STS 引导启动项目中使用这个 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;
}

}

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

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

有 3 处明显的错误和 1 处不太明显的错误。

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

修复纵横比

您当前的方面没有使用 ProceedingJoinPoint,因此从不进行实际的方法调用。其次,如果你现在有一个方法 return 是一个值,它会突然 return null。因为您没有在 ProceedingJoinPoint 上调用 proceed

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

创建一个 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") );
    }

}

添加 属性 以启用 class 代理

src\main\resources 中的 application.properties 添加以下 属性,值为 true

spring.aop.proxy-target-class=true