spring aop类内部调用不拦截原因及解决方案

本文探讨了在Spring框架下如何处理服务层未标记@Transactional的方法调用已标记的方法时的事务管理问题,提供了两种解决方案,并介绍了相关原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout=36000, rollbackFor=Exception.class)
public void test(){

    List<InfoCompanyUser> list = new ArrayList<InfoCompanyUser>();

    InfoCompanyUser u = new InfoCompanyUser();
    u.setUsername("68112710000");
    u.setStatus(1);
    list.add(u);

    u = new InfoCompanyUser();
    u.setUsername("68112710001");
    u.setStatus(1);
    list.add(u);

    u = new InfoCompanyUser();
    u.setUsername("68112710002");
    u.setStatus(1);
    list.add(u);

    infoCompanyUserMapper.updateBatch(list);

    //throw new RuntimeException("测试插入事务");

    int i = 1/0;
}


public void insertTest(){

    // aop拦截在service层,需要调用其内部方法时, 直接调用无法拦截aop内部调用,所以需要设置其代理,此时调用内部即可拦截
    getService().test();
    //getService1().test();
    //throw new RuntimeException("测试插入事务");
    int i = 1/0;
}

当service中的某个没标注@Transactional的方法调用另一个标注了@Transactional的方法时,没开启事务

@Transactional其实就是一个aop代理,是一个cglib动态代理

原因:调用内部方法时候,指向目标对象,不会执行切面事务,而调用标注@Transactional的方法时,使用的是代理对象,执行了切面事务

解决方法

/**
     * 方案一--从beanFactory中获取对象
     *
     * @Author: wpf
     * @Date: 15:00 2018/5/31
     * @Description: 
     * @param  * @param null  
     * @return   
     */
    private RemoteAuditService getService(){
        return SpringContextUtil.getBean(this.getClass());
    }

    /**
     * 方案二--获取代理对象
     *
     * @Author: wpf
     * @Date: 15:00 2018/5/31
     * @Description: 
     * @param  * @param null  
     * @return   
     */
    private RemoteAuditService getService1(){
        // 采取这种方式的话, 注解到类上即可
        //@EnableAspectJAutoProxy(exposeProxy=true,proxyTargetClass=true)
        //必须设置为true
        return AopContext.currentProxy() !=  null? (RemoteAuditService)AopContext.currentProxy() : this;
    }
@Component
public class SpringContextUtil implements ApplicationContextAware {

	private static ApplicationContext applicationContext = null;
	
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		if(SpringContextUtil.applicationContext == null){
			SpringContextUtil.applicationContext = applicationContext;
		}
		
	}

	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}

	
	public static Object getBean(String name){
		return getApplicationContext().getBean(name);
	}
	
	public static <T> T getBean(Class<T> clazz){
		return getApplicationContext().getBean(clazz);
	}
	
}


参考:https://blog.youkuaiyun.com/dream_broken/article/details/72911148


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值