浅谈@Async和@Transaction


@Async注解使用条件:

1、@Async注解一般用在类的方法上,如果用在类上,那么这个类所有的方法都是异步执行的;

2、所使用的@Async注解方法的类对象应该是Spring容器管理的bean对象;

3、调用异步方法类上需要配置上注解@EnableAsync。

使用注意:

1、默认情况下(即@EnableAsync注解的mode=AdviceMode.PROXY),同一个类内部没有使用@Async注解修饰的方法调用@Async注解修饰的方法,是不会异步执行的,这点跟 @Transitional 注解类似,底层都是通过动态代理实现的(详见:Java中的引用和动态代理的实现详解)。如果想实现类内部自调用也可以异步,则需要切换@EnableAsync注解的mode=AdviceMode.ASPECTJ;

2、任意参数类型都是支持的,但是方法返回值必须是void或者Future类型。当使用Future时,你可以使用 实现了Future接口的ListenableFuture接口或者CompletableFuture类与异步任务做更好的交互。如果异步方法有返回值,没有使用Future<V>类型的话,调用方获取不到返回值。

循环依赖问题解决:

A的某个field或者setter依赖了B的实例对象,同时B的某个field或者setter依赖了A的实例对象,Spring通过三级缓存解决循环依赖。同样对于循环依赖的场景,构造器注入和prototype类型的属性注入都会初始化Bean失败,因为@Service默认是单例的,所以单例的属性注入是可以成功的。

总结:

1、构造器注入和prototype类型的field注入发生循环依赖时都无法初始化;

2、field注入单例的bean时,尽管有循环依赖,但bean仍然可以被成功初始化。详见:Spring-bean的循环依赖以及解决方式

但是如果A类里面方法使用了 @Async 注解,就引起了循环依赖报错,这是为什么呢。查阅官方文档:Async注解初始化

NOTE: AsyncConfigurer configuration classes get initialized early in the application context bootstrap. If you need any dependencies on other beans there, make sure to declare them 'lazy' as far as possible in order to let them go through other post-processors as well.

在Spring 启动过程中Async注解为类创建代理类,这样Spring 三级缓存中就没有单例bean的早期引用对象而是Async代理对象,缓存里面找不到bean原始早期对象就引起报错。

解决方法是为注入的其他类增加懒加载@Lazy注解,解决循环依赖报错问题。

懒加载@Lazy:

默认情况下 Bean 等同于 @Lazy(false),在 IOC 容器启动的时候就创建了。如果定义 Bean 的时候加上 @Lazy ,则在 IOC 容器加载的时候,该 Bean 不会被初始化,在调用该 Bean 的时候才会被初始化。

插播sql注入问题:

sql中经常用like进行模糊查询,而模糊查询就要用到百分号“%”,下划线“_”这些通配符,其中“%”匹配任意多个字符,“_”匹配单个字符。如果我们想要模糊查询带有通配符的字符串,如“60%”,“user_name”,就需要对通配符进行转义,有两种方式,如下:

1、反斜杠是转义符,通过反斜杠来转义%,使其不再是通配符。这里第一个%是通配符,第二个%不是通配符。

select percent from score where percent like '%0\%';

2、这种是通过escape关键字进行转义,将特定符号后的字符进行转义,这里斜杠后面的%就不再是通配符,斜杠之前的%仍然起通配符作用。

select percent from score where percent like '%0/%' escape '/';

建议concat配合escape使用。

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM