https://www.cnblogs.com/pickKnow/p/11138118.html
在这一篇博客中,已经通过AOP 思想了事务的功能,通过环绕通知,以及异常通知,实现能够在指定的方法前后调用开启事务,提交事务,回滚事务的功能。
在Spring中,已经通过注解@Transactional 实现了这一功能,具体spring.xml如下:
<!-- 配置事务 --> <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 开启事务 --> <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
代码上只需在方法上加上:@Transactional
@Transactional public void addUser() { // 添加到数据库 System.out.println("开始添加"); userDao.add(1, "tom", "12"); int i = 1 / 0; }
2,注解
分类:内置注解(也成为元注解 jdk 自带注解)、自定义注解(Spring框架)
什么是内置注解
(1) @SuppressWarnings 再程序前面加上可以在javac编译中去除警告--阶段是SOURCE
(2) @Deprecated 带有标记的包,方法,字段说明其过时----阶段是SOURCE
(3)@Overricle 打上这个标记说明该方法是将父类的方法重写--阶段是SOURCE
@Overricle 案例演示
@Override
public String toString() {
return null;
}
@Deprecated案例演示
new Date().parse("");
@SuppressWarnings 案例演示
@SuppressWarnings({ "all" })
public void save() {
java.util.List list = new ArrayList();
}
实现自定义注解
元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:
@Target
@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
2.@Retention
表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
3.@Documented
4.@Inherited
实现一个注解:
@Target({ElementType.METHOD}) //范围 @Retention(RetentionPolicy.RUNTIME) //运行时候 要加 反射需要用到 @Inherited @Documented public @interface User { String username() default "tom"; int age() default 18; String[] arrays(); }
public class App { @User(username = "Jim", arrays = { "basketball" }, age = 20) public void addUser() { System.out.println("Annotation"); } public static void main(String[] args) throws ClassNotFoundException { // 获取到class信息 Class<?> clazz = Class.forName("com.hella.thread.annotation.App"); // 获取方法 Method[] methods = clazz.getDeclaredMethods(); // 循环遍历每个方法上@User 的注解 for (Method method : methods) { User annotation = method.getDeclaredAnnotation(User.class); if (annotation != null) { System.out.println(annotation.age()); System.out.println(annotation.username()); } } } }
3,通过自定义注解来实现@Transactional 的功能
1,自定义注解
@Target({ ElementType.METHOD }) // 范围 @Retention(RetentionPolicy.RUNTIME) // 运行时候 要加 反射需要用到 @Inherited @Documented public @interface DefTransactional { }
2,通过AOP 在每个方法调用前通过反射区获取方法上是否有指定的自定义注解,如果有开启事务,异常回滚事务
Component @Aspect // 这是一个切面类,用来监测方法的调用,调用前判断是有@DefTransactional 注解 @Scope("prototype") // 保证事务的隔离性,让每个对象都是一个新的对象,保证线程安全 public class AopDefTransactional { @Autowired private TransactionUtils transactionUtils; // 环绕通知 @Around("execution (* com.hella.thread.aoptransaction.service.UserService.*(..) )") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { // 1 找到对应的方法,通过方法名和参数类型 因为会有重载 TransactionStatus transactionStatus = begin(proceedingJoinPoint); proceedingJoinPoint.proceed(); // 4 提交事务 commit(transactionStatus); } // 异常通知 @AfterThrowing("execution (* com.hella.thread.aoptransaction.service.UserService.addUser(..) )") public void afterThrowing() { System.out.println("####自定义注解事务回滚"); transactionUtils.rollback(); } private void commit(TransactionStatus transactionStatus) { if (transactionStatus != null) { // 提交事务 System.out.println("####自定义注解事务提交"); transactionUtils.commit(transactionStatus); } } private TransactionStatus begin(ProceedingJoinPoint proceedingJoinPoint) throws NoSuchMethodException, SecurityException { DefTransactional annotation = findMethodByProceedingJoinPoint(proceedingJoinPoint); if (annotation == null) { // 开启事务 System.out.println("方法上没有注解"); return null; } System.out.println("####自定义注解事务开启"); TransactionStatus transactionStatus = transactionUtils.begin(); return transactionStatus; } private DefTransactional findMethodByProceedingJoinPoint(ProceedingJoinPoint proceedingJoinPoint) throws NoSuchMethodException, SecurityException { // 获取到字节码信息 Class<?> clazz = proceedingJoinPoint.getTarget().getClass(); // 获取到方法名称 String methodName = proceedingJoinPoint.getSignature().getName(); // 获取参数 Class<?>[] par = ((MethodSignature) proceedingJoinPoint.getSignature()).getParameterTypes(); // 获取到正在执行的方法 Method method = clazz.getDeclaredMethod(methodName, par); DefTransactional annotation = method.getDeclaredAnnotation(DefTransactional.class); if (annotation == null) { System.out.println("没有注解"); return null; } return annotation; } }
最后在方法上添加事务
@DefTransactional public void addUser() { // 添加到数据库 System.out.println("开始添加"); userDao.add(1, "tom", "12"); int i = 1/0; }