国外知名设计网站大全,html 做网站的模板,一般做网站的在哪里找,产品开发流程图上一节#xff0c;主要分析了 被标记为事务的方法互相调用#xff0c;事务失效的原因#xff0c;思考比较多#xff0c;这一节主要说说解决方案#xff0c;思考会少一些。解决方案的核心#xff1a; 通过代理对象去调用方法1.把方法放到不同的类#xff1a;如果想学习Ja…上一节主要分析了 被标记为事务的方法互相调用事务失效的原因思考比较多这一节主要说说解决方案思考会少一些。解决方案的核心 通过代理对象去调用方法1.把方法放到不同的类如果想学习Java工程化、高性能及分布式、深入浅出。微服务、SpringMyBatisNetty源码分析的朋友可以加我的Java高级交流854630135群里有阿里大牛直播讲解技术以及Java大型互联网技术的视频免费分享给大家。我们需要新建一个接口public interface OtherService {void insertCodeMonkey();
}
再定义一个类去实现这个接口Service
public class OtherServiceImpl implements OtherService {AutowiredAccountMapper mapper;OverrideTransactional(propagationPropagation.REQUIRES_NEW)public void insertCodeMonkey() {Account account new Account();account.setAccount(CodeMonkey);account.setPassword(CodeMonkey);mapper.insert(account);int a 1 / 0;}
}
修改原本的实现类Service
public class AccountSerivceImpl implements AccountService {AutowiredAccountMapper mapper;AutowiredOtherService otherService;TransactionalOverridepublic void insertCodeBear() {try {otherService.insertCodeMonkey();} catch (Exception e) {e.printStackTrace();}Account account new Account();account.setAccount(CodeBear);account.setPassword(CodeBear);mapper.insert(account);}
}
运行查看数据库只有一条数据insertCodeBear方法执行成功了insertCodeMonkey执行失败并且回滚了。让我们再看看控制台的日志如果想学习Java工程化、高性能及分布式、深入浅出。微服务、SpringMyBatisNetty源码分析的朋友可以加我的Java高级交流854630135群里有阿里大牛直播讲解技术以及Java大型互联网技术的视频免费分享给大家。可以看到是开了两个事务去执行的。这种解决方案最简单不需要了解其他东西但是这种方案需要修改代码结构本来两个方法都是属于同一个类的现在需要强行把它们拆开。2. AopContext我们的目标是要在实现类中获取本类的代理对象Spring提供了Aop上下文即AopContext通过AopContext可以很方便的获取到代理对象Service
public class AccountSerivceImpl implements AccountService {AutowiredAccountMapper mapper;TransactionalOverridepublic void insertCodeBear() {try {((AccountService)AopContext.currentProxy()).insertCodeMonkey();} catch (Exception ex) {ex.printStackTrace();}Account account new Account();account.setAccount(CodeBear);account.setPassword(CodeBear);mapper.insert(account);}Transactional(propagation Propagation.REQUIRES_NEW)Overridepublic void insertCodeMonkey() {Account account new Account();account.setAccount(CodeMonkey);account.setPassword(CodeMonkey);mapper.insert(account);int a 1 / 0;}
}
当写好代码很愉快的去测试发现竟然报错了:翻译下不能找到当前的代理需要设置exposeProxy属性为 true使其可以。expose字面意思就是 暴露。也就是说 我们需要允许暴露代理。我们需要在Spring Boot启动类上一个注解EnableAspectJAutoProxy(exposeProxy true)
SpringBootApplication
MapperScan(basePackages com.codebear.Dao)
public class SpringbootApplication {public static void main(String[] args) throws Exception {SpringApplication.run(SpringbootApplication.class, args);}
}
再次运行确实是开启了两个事务去执行的。再看看数据库也没有问题。3. ApplicationContextService
public class AccountSerivceImpl implements AccountService {AutowiredAccountMapper mapper;AutowiredApplicationContext context;AccountService service;PostConstructprivate void setSelf() {service context.getBean(AccountService.class);}TransactionalOverridepublic void insertCodeBear() {try {service.insertCodeMonkey();} catch (Exception e) {e.printStackTrace();}Account account new Account();account.setAccount(CodeBear);account.setPassword(CodeBear);mapper.insert(account);}Transactional(propagation Propagation.REQUIRES_NEW)Overridepublic void insertCodeMonkey() {Account account new Account();account.setAccount(CodeMonkey);account.setPassword(CodeMonkey);mapper.insert(account);int a 1 / 0;}
}
验证的图片就省略了。此方法不适用于prototype在这里我用了一个PostConstruct注解在初始化的时候会调用被PostConstruct标记的方法(注意仅仅是初始化的时候才会被调用。以后都不会被调用了大家可以打个断点试一下)这里这么做的目的就是为了提升一下效率不用每次都getBean。所以如果这个类是prototype的就不适用这个方法了。如果是prototype的话就在insertCodeBear方法中使用getBean方法吧。上两种方法比较方便没有新建其他的接口或者是类但是没有很好的封装获得Aop代理对象的过程也不是很符合 迪比特法则也就是最少知识原则。4. 重写BeanPostProcessor接口关于这个接口是做什么的这里就不详细阐述了简单的来说这是Spring提供的接口我们可以通过重写它在初始化Bean之前或者之后自定义一些额外的逻辑。首先我们需要定义一个接口public interface WeavingSelfProxy {void setSelfProxy(Object bean);
}
要获得代理对象的类需要去实现它Service
public class AccountSerivceImpl implements AccountService, WeavingSelfProxy {AutowiredAccountMapper mapper;AccountService service;Overridepublic void setSelfProxy(Object bean) {System.out.println(进入到setSelfProxy方法);service (AccountService) bean;}TransactionalOverridepublic void insertCodeBear() {try {service.insertCodeMonkey();} catch (Exception e) {e.printStackTrace();}Account account new Account();account.setAccount(CodeBear);account.setPassword(CodeBear);mapper.insert(account);}Transactional(propagation Propagation.REQUIRES_NEW)Overridepublic void insertCodeMonkey() {Account account new Account();account.setAccount(CodeMonkey);account.setPassword(CodeMonkey);mapper.insert(account);int a 1 / 0;}
}
重写BeanPostProcessor接口如果想学习Java工程化、高性能及分布式、深入浅出。微服务、SpringMyBatisNetty源码分析的朋友可以加我的Java高级交流854630135群里有阿里大牛直播讲解技术以及Java大型互联网技术的视频免费分享给大家。Component
public class SetSelfProxyProcessor implements BeanPostProcessor {Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if(bean instanceof WeavingSelfProxy){System.out.println(实现了WeavingSelfProxy接口);((WeavingSelfProxy) bean).setSelfProxy(bean);}return bean;}
}
这样就可以了验证的图片也省略了。以上就是四种解决方案可以说 各有千秋没有哪个好哪个坏只有适不适合。如果想学习Java工程化、高性能及分布式、深入浅出。微服务、SpringMyBatisNetty源码分析的朋友可以加我的Java高级交流854630135群里有阿里大牛直播讲解技术以及Java大型互联网技术的视频免费分享给大家。