先了解什么是注解
注解
Jdk1.5新增新技术,注解。很多框架为了简化代码,都会提供有些注解。可以理解为插件,是代码级别的插件,在类的方法上写:@XXX,就是在代码上插入了一个插件。
注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。
注解分类:内置注解(也成为元注解 jdk 自带注解)、自定义注解(Spring框架)
什么是内置注解
(1) @SuppressWarnings 再程序前面加上可以在javac编译中去除警告--阶段是SOURCE
(2) @Deprecated 带有标记的包,方法,字段说明其过时----阶段是SOURCE
(3)@Overricle 打上这个标记说明该方法是将父类的方法重写--阶段是SOURCE
实现自定义注解
元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:
@Target
@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
- CONSTRUCTOR:用于描述构造器
- FIELD:用于描述域
- LOCAL_VARIABLE:用于描述局部变量
- METHOD:用于描述方法
- PACKAGE:用于描述包
- PARAMETER:用于描述参数
- TYPE:用于描述类、接口(包括注解类型) 或enum声明
表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
3.@Documented
4.@interface
@Target(value = { ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) public @interface AddAnnotation { int userId() default 0; String userName() default "默认名称"; String[]arrays(); } 反射读取注解信息 public static void main(String[] args) throws ClassNotFoundException { Class classInfo = Class.forName("com.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); } } }
自定义事务注解
//编程事务(需要手动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.itmayiedu.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.itmayiedu.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", 20); int i = 1 / 0; System.out.println("################"); userDao.add("test002", 21); }
Spring事物传播行为
Spring中事务的定义:
Propagation(key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。)有以下选项可供使用:
PROPAGATION_REQUIRED—如果当前有事务,就用当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。//如果外层方法没有事务,就会以非事务进行执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
--- 如果当前有事务,就是以非事务进行执行
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
默认传播行为为REQUIRED