Java注释
00 分钟
2022-4-26
2023-4-26
type
status
date
slug
summary
tags
category
icon
password
URL

@Service

用于标注业务层组件

@Controller

用于标注控制层组件

@Repository

用户标注数据访问组件,即DAO组件

@Component

泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注

@Resource

由J2EE提供,默认按照byName自动注入,Spring将@Resource注解的name属性解析为bean的名字,type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性则使用byType自动注入策略。

@Autowired

由Spring提供,只按照byType注入,默认情况下必须要求依赖对象存在,如果要允许null值,可以设置它的required属性为false,如果想使用名称装配可以结合@Qualifier注解进行使用

@Resource & @Autowired

一旦关于Spring的注解出现在类里,被注解的这个类是从Spring容器中取出来的,那调用的实现类也需要被Spring容器管理,必须加上@Component、@Service等注解

@SpringBootTest

@SpringBootTest替代了spring-test中的@ContextConfiguration注解,目的是加载ApplicationContext,启动spring容器。一般情况下,使用@SpringBootTest后,Spring将加载所有被管理的bean,基本等同于启动了整个服务,此时便可以开始功能测试

@RunWith

是Junit4提供的注解,作用就是一个运行期,指的是用JUnit4来运行,将Spring和Junit连接了起来,假如使用Junit5,不再需要使用@ExtendWith注解,@SpringBootTest和其他@*Test默认已经包含了该注解

@ActiveProfiles

一般声明在UT测试类上,用于指定这个测试类里的测试方式运行时的profiles

@Transactional

作用于类:表示当前类所有public方法都配置相同的事务属性信息。 作用于方法:当类配置了@Transactional,方法也配置了@Transactional,方法的事务会覆盖类的事务配置信息 作用于接口:不推荐这种使用方法,因为一旦标注在Interface上并且配置了Spring AOP使用CGLib动态代理,将会导致@Transactional注解失效 什么时候会失效:: 1、应用在非public修饰的方法上,Transactional将会失效。之所以会失效是因为在Spring AOP代理时,TransactionInterceptor(事务拦截器)在目标方法执行前后进行拦截,DynamicAdvisedInterceptor(CglibAopProxy的内部类)的intercept方法或JdkDynamicAopProxy的invoke方法会简介调用AbstractFallbackTransactionAttributeSource的 computeTransactionAttribute 方法,获取Transactional 注解的事务配置信息。
注意:protected、private修饰的方法上使用@Transactional注解,虽然事务无效,但不会有任何报错,这是我们很容易犯错的一点
2、@Transactional 注解属性 propagation 设置错误 这种失效是由于配置错误,若是错误的配置以下三种 propagation,事务将不会发生回滚。 TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。 TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。 TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。 3、@Transactional 注解属性 rollbackFor 设置错误 rollbackFor 可以指定能够触发事务回滚的异常类型。Spring默认抛出了未检查unchecked异常(继承自 RuntimeException 的异常)或者 Error才回滚事务;其他异常不会触发回滚事务。如果在事务中抛出其他类型的异常,但却期望 Spring 能够回滚事务,就需要指定 rollbackFor属性。
// 希望自定义的异常可以进行回滚 @Transactional(propagation= Propagation.REQUIRED,rollbackFor= MyException.class 复制代码若在目标方法中抛出的异常是 rollbackFor 指定的异常的子类,事务同样会回滚。Spring源码如下:
4、同一个类中方法调用,导致@Transactional失效 开发中避免不了会对同一个类里面的方法调用,比如有一个类Test,它的一个方法A,A再调用本类的方法B(不论方法B是用public还是private修饰),但方法A没有声明注解事务,而B方法有。则外部调用方法A之后,方法B的事务是不会起作用的。这也是经常犯错误的一个地方。 那为啥会出现这种情况?其实这还是由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理。
5、异常被你的 catch“吃了”导致@Transactional失效 这种情况是最常见的一种@Transactional注解失效场景,
如果B方法内部抛了异常,而A方法此时try catch了B方法的异常,那这个事务还能正常回滚吗? 答案:不能! 会抛出异常:
因为当ServiceB中抛出了一个异常以后,ServiceB标识当前事务需要rollback。但是ServiceA中由于你手动的捕获这个异常并进行处理,ServiceA认为当前事务应该正常commit。此时就出现了前后不一致,也就是因为这样,抛出了前面的UnexpectedRollbackException异常。 spring的事务是在调用业务方法之前开始的,业务方法执行完毕之后才执行commit or rollback,事务是否执行取决于是否抛出runtime异常。如果抛出runtime exception 并在你的业务方法中没有catch到的话,事务会回滚。 在业务方法中一般不需要catch异常,如果非要catch一定要抛出throw new RuntimeException(),或者注解中指定抛异常类型@Transactional(rollbackFor=Exception.class),否则会导致事务失效,数据commit造成数据不一致,所以有些时候try catch反倒会画蛇添足。 6、数据库引擎不支持事务 这种情况出现的概率并不高,事务能否生效数据库引擎是否支持事务是关键。常用的MySQL数据库默认使用支持事务的innodb引擎。一旦数据库引擎切换成不支持事务的myisam,那事务就从根本上失效了。

@Repository

用于将数据库访问层(DAO层)的类表示为Spring Bean,具体指需要将改注解标注在DAO类上即可。该注解只能标注在DAO类上,因为改注解的作用不只是将类识别为Bean,同时他还能将所标注的类中抛出的数据访问异常封装为Spring的数据访问异常类型。Spring本身提供了一个丰富的并且是与具体的数据访问技术无关的数据访问异常结构,用于封装不同的持久层框架抛出的异常,使得独立于底层的框架

@Mapper

用在接口类上,在编译之后会生成相应的接口实现类

@MapperScan

扫描指定包下所有的接口类,然后所有接口编译之后都会生成相应的实现类 添加的位置是在SpringBootApplication启动类上面添加

评论