今日遇到AOP失效的问题,恰好我之前也遇到过类似地问题,于是统一总结一下:
(1)AOP使得@Autowired失效
下面是群里老大哥给出的解释:
解决方案:将private改成protected即可。
(2)两个动态代理方法引起的其中一个失效
因为之前的代码忘了是哪个项目中的了,直接采用网上的样例的
样例取之于:https://blog.csdn.net/u012373815/article/details/77345655
在对象内部的方法中调用该对象的其他使用aop机制的方法,被调用方法的aop注解失效。
如下代码:
public class TicketService{
//买火车票
@Transactional
public void buyTrainTicket(Ticket ticket){
System.out.println("买到了火车票");
try {
//在同一个类中的方法,调用 aop注解(@Transactional 注解也是aop 注解) 的方法,会使aop 注解失效.
//此时如果 sendMessage()的发送消息动作失败抛出异常,“消息存入数据库“动作不会回滚。
sendMessage();
} catch (Exception e) {
logger.warn("发送消息异常");
}
}
//买到车票后发送消息
@Transactional
public void sendMessage(){
System.out.println("消息存入数据库");
System.out.println("执行发送消息动作");
}
}
springboot 解决方案:
新建获取代理对象的工具类SpringUtil,去ApplicationContext 中取我门的代理对象了
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
if (SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
//通过class获取Bean.
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
//通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name,Class<T> clazz){
return getApplicationContext().getBean(name, clazz);
}
}
修改范例:
public class TicketService{
//买火车票
@Transactional
public void buyTrainTicket(Ticket ticket){
System.out.println("买到了火车票");
try {
//通过代理对象去调用sendMessage()方法
SpringUtil.getBean(this.getClass()).sendMessage();
} catch (Exception e) {
logger.warn("发送消息异常");
}
}
@Transactional
public void sendMessage(){
System.out.println("消息存入数据库");
System.out.println("执行发送消息动作");
}
}