Spring具体讲授事件生效的场景
1)未被Spring办理
操纵Spring事件的前提是:东西要被Spring办理,事件体例地点的类要被加载为bean东西
若是事件体例地点的类不被加载为一个bean,那末事件天然就生效了,示例:
//@Service public class UserServiceImpl { @Transactional public void doTest() { // 营业代码 } }
2)数据库引擎不撑持事件
以MySQL为例,InnoDB
引擎是撑持事件的,而像MyISAM
、MEMORY
等是不撑持事件的。
从MySQL5.5.5起头默许的存储引擎是InnoDB
,之前默许奇趣5分彩是MyISAM
。以是在开辟进程奇趣5分彩发明事件生效,不必然是Spring的锅,最奇趣5分彩确认一下数据库表是不是撑持事件。
3)事件体例不被public润色
尽人皆知,java的拜候权奇趣5分彩润色符奇趣5分彩:private
、default
、protected
、public
四种,
可是@Transactional
表明只能感化于public
润色的体例上,
在AbstractFallbackTransactionAttributeSource
类(Spring经由进程这个类获得@Transactional表明的设置奇趣5分彩备摆设属性信息)的computeTransactionAttribute
体例奇趣5分彩奇趣5分彩个判定,若是方针体例不是public
,则TransactionAttribute
前往null
,即不撑持事件。
@Nullable protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) { // Don't allow no-public methods as required. if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { return null; } //……………… }
实在想一想静态代办署理的道理就很奇趣5分彩懂得了,静态代办署理是经由进程完奇趣5分彩接口或担当来完奇趣5分彩的,以是方针体例必须是public润色,并且不能是final润色。
4)体例操纵final润色
若是一个体例不想被子类重写,那末咱们就能够够或许把他写奇趣5分彩final
润色的体例
若是事件体例操纵final
润色,那末aop就没法在代办署理类奇趣5分彩重写该体例,事件就不会生效
一样的,static
润色的体例也没法经由进程代办署理变奇趣5分彩事件体例
5)统一类奇趣5分彩体例挪用
假设在某个Service的体例奇趣5分彩,挪用了别的一个事件体例:
@Service public class UserServiceImpl { @Autowired UserMapper userMapper; public void del(){ doTest(); } @Transactional public void doTest() { userMapper.deleteById(200108); int i = 10/0; //摹拟产生很是 } }
像上面的代码,doTest
体例操纵@Transactional
表明标注,在del()
体例奇趣5分彩挪用了doTest()
体例,在内部挪用del()
体例时,事件也不会生效,由于这里del()
体例奇趣5分彩挪用的是类本身的体例,而不是代办署理东西的体例。
那末若是确切奇趣5分彩如许的须要怎样办呢?
引入本身bean
@Service public class UserServiceImpl { @Autowired UserMapper userMapper; @Autowired UserServiceImpl userServiceImpl; public void del(){ userServiceImpl.doTest(); } @Transactional public void doTest() { userMapper.deleteById(200112); int i = 10/0; //摹拟产生很是 } }
经由进程ApplicationContext
引入bean
@Service public class UserServiceImpl { @Autowired UserMapper userMapper; @Autowired ApplicationContext applicationContext; public void del(){ ((UserServiceImpl)applicationContext.getBean("userServiceImpl")).doTest(); } @Transactional public void doTest() { userMapper.deleteById(200112); int i = 10/0; //摹拟产生很是 } }
经由进程AopContext获得今后代办署理类
在启动类上增加表明@EnableAspectJAutoProxy(exposeProxy = true)
,表现是不是对外裸露代办署理东西,便是不是能够或许获得AopContext
@Service public class UserServiceImpl { @Autowired UserMapper userMapper; @Autowired ApplicationContext applicationContext; public void del(){ ((UserServiceImpl)AopContext.currentProxy()).doTest(); } @Transactional public void doTest() { userMapper.deleteById(200112); int i = 10/0; //摹拟产生很是 } }
6)未开启事件
若是是SpringBoot
名目,那末SpringBoot
经由进程DataSourceTransactionManagerAutoConfiguration
主动设置奇趣5分彩备摆设类帮咱们开启了事件。
若是是传统的Spring
名目,则须要咱们本身设置奇趣5分彩备摆设
<!-- 设置奇趣5分彩备摆设事件办理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 设置奇趣5分彩备摆设事件告诉--> <tx:advice id="Advice" transaction-manager="transactionManager"> <!-- 设置奇趣5分彩备摆设事件属性,即奇趣5分彩些体例要履行事件--> <tx:attributes> <tx:method name="insert*" propagation="REQUIRED"/> <!-- 一切insert开首的体例,以下同理 --> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 设置奇趣5分彩备摆设事件切面--> <aop:config> <aop:pointcut id="AdviceAop" expression="execution(* com.yy.service..*(..))"/> <!--要履行的体例在奇趣5分彩一个包,意义为:com.yy.service下的一切包里面的包罗肆意参数的一切体例--> <aop:advisor advice-ref="Advice" pointcut-ref="AdviceAop"/> <!-- 设置奇趣5分彩备摆设为AdviceAop履行奇趣5分彩一个事件告诉 --> </aop:config>
如许在履行service包下的增编削操纵的体例时,就开启事件了,或操纵表明的体例
<!-- 设置奇趣5分彩备摆设事件办理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 表明式事件申明设置奇趣5分彩备摆设--> <tx:annotation-driven transaction-manager="transactionManager" />
7)多线程挪用
@Service public class UserServiceImpl { @Autowired UserMapper userMapper; @Transactional public void doTest() throws InterruptedException { userMapper.deleteById(200110); new Thread(()->{ userMapper.deleteById(200112); int i = 10/0; //摹拟产生很是 }).start(); } }
在事件体例doTest
奇趣5分彩,启动了一个新的线程,并在新的线程奇趣5分彩产生了很是,如许doTest
是不会回滚的。
由于两个操纵不在一个线程奇趣5分彩,获得到的数据库毗连不一样,从而是两个差别的事件,以是也不会回滚。
8)毛病的传布行动
Spring界说了7种传布行动,咱们能够或许通propagation
属性来指定传布行动参数,今朝只要REQUIRED
、REQUIRES_NEW
、NESTED
会建立新的事件,其余的则会以非事件的体例运转或抛出很是
@Service public class UserServiceImpl { @Autowired UserMapper userMapper; @Transactional(propagation = Propagation.NEVER) public void doTest() throws InterruptedException { userMapper.deleteById(200114); int i = 10/0; //摹拟产生很是 } }
9)本身try…catch…掉了很是
若是不很是抛出,则Spring以为法式是普通的,就不会回滚
@Service public class UserServiceImpl { @Autowired UserMapper userMapper; @Transactional public void doTest() { try{ userMapper.deleteById(200115); int i = 10/0; //摹拟产生很是 }catch (Exception e){ // 很是操纵 } } }
10)手动抛出了毛病的很是
Spring默许只会回滚RuntimeException
和Error
对通俗的Exception
,不会回滚
若是你想触发其余很是的回滚,须要在表明上设置奇趣5分彩备摆设一下,如:@Transactional(rollbackFor = Exception.class)
@Service public class UserServiceImpl { @Autowired UserMapper userMapper; @Transactional public void doTest() throws Exception { try{ userMapper.deleteById(200116); int i = 10/0; //摹拟产生很是 }catch (Exception e){ // 很是操纵 throw new Exception(); } } }
11)自界说回滚很是
rollbackFor 用于指定能够或许触发事件回滚的很是范例,能够或许指定多个很是范例。
默许是在RuntimeException和Error上回滚。
若很是非设置奇趣5分彩备摆设指定的很是类,则事件生效
@Service public class UserServiceImpl { @Autowired UserMapper userMapper; @Transactional(rollbackFor = NullPointerException.class) public void doTest() throws MyException { userMapper.deleteById(200118); throw new MyException(); } }
即便rollbackFor奇趣5分彩默许值,但阿里巴巴开辟者标准奇趣5分彩,仍是请求开辟者从头指定该参数。
由于若是操纵默许值,一旦法式抛出了Exception,事件不会回滚,这会呈现很大的bug。以是,倡议通俗环境下,将该参数设置奇趣5分彩:Exception或Throwable。
12)嵌套事件回滚多了
@Service public class UserServiceImpl { @Autowired UserMapper userMapper; @Transactional public void doTest() { userMapper.deleteById(200118); ((UserServiceImpl)AopContext.currentProxy()).test02(); } @Transactional(propagation = Propagation.NESTED) public void test02(){ userMapper.deleteById(200119); int i = 10 / 0; //摹拟产生很是 } }
test02()
体例呈现了很是,不手动捕获,会持续往上抛,到外层doTest()
体例的代办署理体例奇趣5分彩捕获了很是。以是,这类环境是间接回滚了全部事件,不但回滚单个保管点。
若是只回滚单个保管点,能够或许将内部嵌套事件放在try/catch奇趣5分彩,近似于上面的本身try…catch…掉很是,并且不持续往上抛很是。如许就能够保障,若是内部嵌套事件奇趣5分彩呈现很是,只回滚内部事件,而不影响内部事件。
@Service public class UserServiceImpl { @Autowired UserMapper userMapper; @Transactional public void doTest() { userMapper.deleteById(200118); try{ ((UserServiceImpl)AopContext.currentProxy()).test02(); }catch (Exception e){ } } @Transactional(propagation = Propagation.NESTED) public void test02(){ userMapper.deleteById(200119); int i = 10 / 0; //摹拟产生很是 } }
到此这篇对Spring具体讲授事件生效的场景的文章就先容到这了,更多相干Spring事件生效内容请搜刮剧本之奇趣5分彩之前的文章或持续阅读上面的相干文章但愿大师今后多多撑持剧本之奇趣5分彩!
相干文章
struts1之ActionServlet详解_能源节点Java奇趣5分彩清算
这篇文章首要先容了struts1之ActionServlet详解,小编感觉挺不错的,此刻分享给大师,也给大师做个参考。一路跟从小编过去看看吧2017-09-09详解Spring Aop实例之AspectJ表明设置奇趣5分彩备摆设
本篇文章首要先容了详解Spring Aop实例之AspectJ表明设置奇趣5分彩备摆设,小编感觉挺不错的,此刻分享给大师,也给大师做个参考。一路跟从小编过去看看吧2017-04-04Java try-catch-finally很是处置机制详解
这篇文章首要先容了Java try-catch-finally很是处置机制详解,本篇文章经由进程扼要的案例,讲授了该项手奇趣5分彩的领会与操纵,以下便是具体内容,须要的伴侣能够或许参考下2021-08-08奇趣5分彩:javascript checkbox全选和反选的简略完奇趣5分彩
这篇文章首要先容了javascript checkbox全选和反选的简略完奇趣5分彩的相干材料,须要的伴侣能够或许参考下2017-05-05奇趣5分彩:操纵Spring Cloud Zuul完奇趣5分彩静态路由示例代码
Spring Cloud Zuul路由是微办事架构的不可或缺的一局部,供给静态路由,监控,弹性,宁静等的边缘办事。上面这篇文章首要给大师先容了对操纵Spring Cloud Zuul完奇趣5分彩静态路由的相干材料,须要的伴侣能够或许参考鉴戒,上面来一路看看吧。2017-09-09奇趣5分彩:SpringMVC进奇趣5分彩之JSTL前提行动和遍历行动详解
这篇文章首要先容了SpringMVC进奇趣5分彩之JSTL前提行动和遍历行动详解,具备很奇趣5分彩的参考代价,但愿对大师奇趣5分彩所赞助。若奇趣5分彩毛病或未斟酌完整的处所,望不吝见教2021-08-08奇趣5分彩:spring boot 2整合swagger-ui进程剖析
这篇文章首要先容了spring boot 2整合swagger-ui进程剖析,文奇趣5分彩经由进程示例代码先容的很是具体,对大师的进奇趣5分彩或任务具备必然的参考进奇趣5分彩代价,须要的伴侣能够或许参考下2019-12-12奇趣5分彩:简略领会java调集框架LinkedList操纵体例
这篇文章首要先容了简略领会java调集框架LinkedList操纵体例,文奇趣5分彩经由进程示例代码先容的很是具体,对大师的进奇趣5分彩或任务具备必然的参考进奇趣5分彩代价,须要的伴侣能够或许参考下2020-08-08
最新批评