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 处不太明显的错误。
- 你的方面是错误的,破坏了正确的方法执行。使用环绕方面时,您必须始终 return
Object
并使用 ProceedingJoinPoint
并在其上调用 proceed()
。
- 您正在自己创建 classes 的新实例,Spring,默认情况下,使用基于代理的 AOP,并且只会代理它知道的 bean。
- 在
@PostConstruct
方法中,可能尚未创建代理并且没有任何内容被拦截
- 您需要使用基于 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
我在我的 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 处不太明显的错误。
- 你的方面是错误的,破坏了正确的方法执行。使用环绕方面时,您必须始终 return
Object
并使用ProceedingJoinPoint
并在其上调用proceed()
。 - 您正在自己创建 classes 的新实例,Spring,默认情况下,使用基于代理的 AOP,并且只会代理它知道的 bean。
- 在
@PostConstruct
方法中,可能尚未创建代理并且没有任何内容被拦截 - 您需要使用基于 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