专栏名称: SegmentFault思否
SegmentFault (www.sf.gg)开发者社区,是中国年轻开发者喜爱的极客社区,我们为开发者提供最纯粹的技术交流和分享平台。
目录
相关文章推荐
程序员小灰  ·  清华大学《DeepSeek学习手册》(全5册) ·  昨天  
程序员小灰  ·  3个令人惊艳的DeepSeek项目,诞生了! ·  17 小时前  
OSC开源社区  ·  升级到Svelte ... ·  3 天前  
待字闺中  ·  DeepSeek 爆火带来的大变化 ·  1 周前  
51好读  ›  专栏  ›  SegmentFault思否

手写 Spring 注解版本事务,Spring 事物的七大传播行为

SegmentFault思否  · 公众号  · 程序员  · 2020-01-21 11:46

正文

本文转载于 SegmentFault 社区

作者:codeobj




注解



1、什么是内置注解


(1)@SuppressWarnings 再程序前面加上可以在 javac 编译中去除警告--阶段是 SOURCE
(2)@Deprecated 带有标记的包,方法,字段说明其过时----阶段是 SOURCE
(3)@Overricle 打上这个标记说明该方法是将父类的方法重写--阶段是SOURCE

1.1 @Overricle 案例演示


@Override
public String toString() {
return null;
}
1.2 @Deprecated 案例演示 表示此方法已被弃用
new Date().parse("");
如果已被弃用,则在调用时出现删除线


1.3 @SuppressWarnings  案例演示

     

@SuppressWarnings({ "all" })
public void save() {
java.util.List list = new ArrayList();
}

2、实现自定义注解


元注解的作用就是负责注解其他注解。 Java5.0 定义了 4 个标准的 meta-annotation类型,它们被用来提供对其它 annotation 类型作说明。 Java5.0 定义的元注解:

2.1 @Target


@Target 说明了 Annotation 所修饰的对象范围:Annotation 可被用于 packages、ty pes (类、接口、枚举、Annotation类型) 、类型成员 (方法、构造方法、成员变量、枚举值) 、方法参数和本地变量 (如循环变量、catch 参数) 。在 Annotation 类型的声明中使用了 target 可更加明晰其修饰的目标。

CONSTRUCTOR : 用于描述构造器
FIELD : 用于描述域
LOCAL_VARIABLE : 用于描述局部变量
METHOD : 用于描述方法
PACKAGE : 用于描述包
PARAMETER : 用于描述参数
TYPE : 用于描述类、接口 (包括注解类型) 或 enum 声明


2.2 @Retention


表示需要在什么级别保存该注释信息,用于描述注解的生命周期 (即:被描述的注解在什么范围内有效)

2.3 @Documented

2.4 @Inherited


使用 @interface 定义注解。
@Target(value = ElementType.METHOD )
@Retention(RetentionPolicy.RUNTIME)
// @interface 定义注解
public @interface AddAnnotation {

// 手写Spring事务注解
int userId() default 0;

String userName() default "默认名称";

String[] arrays();

}
反射读取注解信息

public static void main(String[] args) throws ClassNotFoundException {
Class classInfo = Class.forName("com.codeobj.entity.User");
// 获取到所有方法
Method[] methods = classInfo.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
AddAnnotation declaredAnnotation = method.getDeclaredAnnotation(AddAnnotation.class);
if (declaredAnnotation == null) {
// 结束本次循环
continue;
}
// 获取userId
int userId = declaredAnnotation.userId();
System.out.println("userId:" + userId);
// 获取userName
String userName = declaredAnnotation.userName();
System.out.println("userName:" + userName);
// 获取arrays
String[] arrays = declaredAnnotation.arrays();
for (String str : arrays) {
System.out.println("str:" + str);
}
}
}

3、自定义事务注解


//编程事务(需要手动begin 手动回滚 手都提交)
@Component()
@Scope("prototype") // 设置成原型解决线程安全
public class TransactionUtils {

private TransactionStatus transactionStatus;
// 获取事务源
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;

// 开启事务
public TransactionStatus begin() {
transactionStatus = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
return transactionStatus;
}

// 提交事务
public void commit(TransactionStatus transaction) {
dataSourceTransactionManager.commit(transaction);
}

// 回滚事务
public void rollback() {
System.out.println("rollback");
dataSourceTransactionManager.rollback(transactionStatus);
}

}

注解类

@Autowired
private TransactionUtils transactionUtils;

@AfterThrowing("execution(* com.codeobj.service.*.*.*(..))")
public void afterThrowing() throws NoSuchMethodException, SecurityException {
// isRollback(proceedingJoinPoint);
System.out.println("程序发生异常");
// TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
// TransactionStatus currentTransactionStatus =
// TransactionAspectSupport.currentTransactionStatus();
// System.out.println("currentTransactionStatus:" +
// currentTransactionStatus);
transactionUtils.rollback();
}

// // 环绕通知 在方法之前和之后处理事情
@Around("execution(* com.codeobj.service.*.*.*(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

// 调用方法之前执行
TransactionStatus transactionStatus = begin(proceedingJoinPoint);
proceedingJoinPoint.proceed();// 代理调用方法 注意点:如果调用方法抛出异常不会执行后面代码
// 调用方法之后执行
commit(transactionStatus);
}

public TransactionStatus begin(ProceedingJoinPoint pjp) throws NoSuchMethodException, SecurityException {

// // 判断是否有自定义事务注解
ExtTransaction declaredAnnotation = getExtTransaction(pjp);
if (declaredAnnotation == null) {
return null;
}
// 如果有自定义事务注解,开启事务
System.out.println("开启事务");
TransactionStatus transactionStatu = transactionUtils.begin();
return transactionStatu;
}

public void commit(TransactionStatus transactionStatu) {
if (transactionStatu != null) {
// 提交事务
System.out.println("提交事务");
transactionUtils.commit(transactionStatu);
}
}

public ExtTransaction getExtTransaction(ProceedingJoinPoint pjp) throws NoSuchMethodException, SecurityException {
// 获取方法名称
String methodName = pjp.getSignature().getName();
// 获取目标对象
Class> classTarget = pjp.getTarget().getClass();
// 获取目标对象类型
Class>[] par = ((MethodSignature) pjp.getSignature()).getParameterTypes();
// 获取目标对象方法
Method objMethod = classTarget.getMethod(methodName, par);
// // 判断是否有自定义事务注解
ExtTransaction declaredAnnotation = objMethod.getDeclaredAnnotation(ExtTransaction.class);
if (declaredAnnotation == null) {
System.out.println("您的方法上,没有加入注解!");
return null;
}
return declaredAnnotation;

}

// 回滚事务
public void isRollback(ProceedingJoinPoint pjp) throws NoSuchMethodException, SecurityException {
// // 判断是否有自定义事务注解
ExtTransaction declaredAnnotation = getExtTransaction(pjp);
if (declaredAnnotation != null) {
System.out.println("已经开始回滚事务");
// 获取当前事务 直接回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return;
}
}
使用自定义注解
@ExtTransaction
public void add() {
userDao.add("test001"






请到「今天看啥」查看全文