注解(也被称为元数据 )为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便地使用这些数据。
注解的语法比较简单,除了@符号的使用之外,它基本与Java固有的语法一致。Java SE5内置了三种,定义在java.lang中的注解:
·@Override,表示当前的方法定义将覆盖超类中的方法。如果你不小心拼写错误,或者方 法签名对不上被覆盖的方法,编译器就会发出错误提示。
·@Deprecated,如果程序员使用了注解为它的元素,那么编译器会发出警告信息。
·@Suppress Warnings,.关闭不当的编译器警告信息。在Java SE5之前的版本中,也可以使 用该注解,不过会被忽略不起作用。
Java还另外提供了四种注解,专门负责新注解的创建。稍后我们将学习它们。
package com.qf;
public @interface MyAnnotation {
int id() default 0;
String name() default "zhang san" ;
}
@MyAnnotation(id = 22,name="李四")
public void test2(){
}
Java目前只内置了四种元注解。元注解专职负责注解其他的注解:
| 元注解 | 作用 |
|---|---|
| @Target | 表示该注解可以用于什么地方。可能的ElementType参数包括: CONSTRUCTOR:构造器的声明 FIELD:域声明(包括enum实例) LOCAL_VARIABLE:局部变量声明 METHOD:方法声明 PACKAGE:包声明 PARAMETER:参数声明 TYPE:类、接口(包括注解类型)或enum声明 |
| @Retention | 表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括: SOURCE:注解将被编译器丢弃。 CLASS:注解在class-文件中可用,但会被VM丢弃。 RUNTIME:VM将在运行期也保留注解,因此可以通过反射机制读取注解的信息 |
| @Documented | 将此注解包含在Javadoc中。 |
| @Inherited | 允许子类继承父类中的注解。 |
·编写注解处理器解析注解
注解
package com.qf;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Parse {
int age() default 18;
String name() ;
}
反射
package com.qf;
import java.lang.reflect.Method;
public class Test3 {
public static void main(String[] args) {
Class<Test3> test3Class= Test3.class;
for (Method method : test3Class.getMethods()) {
Parse annotation = method.getAnnotation(Parse.class);
if (annotation!=null){
System.out.printf("%s,您的%s方法写的可真好,您今年才%d岁就写出来,真是年轻有为",annotation.name(),method.getName(),annotation.age());
System.out.println();
}
}
}
@Parse(name="张三")
public void test1(){
}
@Parse(age = 22,name="李四")
public void test2(){
}
}
使用反射机制可以动态获取当前class的信息 比如方法的信息、注解信息、方法的参数、属性等;
Class类 代表类的实体,在运行的Java应用程序中表示类和接口
Field类 代表类的成员变量(成员变量也称为类的属性)
Method类 代表类的方法
Constructor类 代表类的构造方法
Class<?> aClass = Class.forName(“com.mayikt.entity.UserEntity”);
Class<?> aClass = Class.forName("com.qf.entity.UserEntity");
UserEntity userEntity = (UserEntity) aClass.newInstance();
userEntity.setName("zhangsan");
userEntity.setUserId(1234);
System.out.println(userEntity);
Class<?> aClass = Class.forName("com.qf.entity.UserEntity");
// 执行有参数构造函数
Constructor<?> constructor = aClass.
getConstructor(Integer.class, String.class);
UserEntity userEntity = (UserEntity) constructor.
newInstance(10, "zhangsan");
System.out.println(userEntity);
Class<?> aClass = Class.forName("com.qf.entity.UserEntity");
// 给私有属性赋值
UserEntity userEntity = (UserEntity) aClass.newInstance();
Field userId = aClass.getDeclaredField("userId");
userId.setAccessible(true); //关闭安全检查,直接通行
userId.set(userEntity,12);
Field name = aClass.getDeclaredField("name");
name.setAccessible(true);
name.set(userEntity,"zhangsan");
System.out.println(userEntity);
假设未设置setAccessible(true),不能通过java语言安全检查,因为你需要访问的是类的私有属性和方法
Exception in thread "main" java.lang.IllegalAccessException: Class com.mayikt.Test001 can not access a member of class com.mayikt.entity.UserEntity with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
如果使用反射给私有属性或者调用私有的方法 都需要设置权限
Class<?> aClass = Class.forName("com.qf.entity.UserEntity");
// 给私有属性赋值
UserEntity userEntity = (UserEntity) aClass.newInstance();
Method mete= aClass.getDeclaredMethod("mete", Integer.class);
mete.setAccessible(true);
Object invoke = mete.invoke(userEntity, 10);
System.out.println(invoke);
@Transactional
public void insertUser() {
try {
user user=new user(new Date(),"place",new Date());
userDao.insert(user);
int i=1/0;
}catch (Exception e){
e.printStackTrace();
}
}
当我们需要在事务控制的service层类中使用try catch 去捕获异常后,就会使事务控制失效,因为该类的异常并没有抛出,就不是触发事务管理机制。怎样才能即使用try catch去捕获异常,而又让出现异常后spring回滚呢,这里就要用到,在service层方法的catch语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常了
例如
@Transactional
public void insertUser() {
try {
user user=new user(new Date(),"place",new Date());
userDao.insert(user);
int i=1/0;
}catch (Exception e){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
e.printStackTrace();
}
}
痛点:每次使用try catch块时,都需要加入 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();手动回滚,代码多重复
注解
package com.qf;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExTransational {
}
手动事务
package com.qf;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
@Component
public class TransactionalUtils {
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
/**
* begin
* @return
*/
public TransactionStatus begin(){
// 设置传播行为
TransactionStatus transaction =
dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
return transaction;
}
/**
* 提交
* @param transaction
*/
public void commit( TransactionStatus transaction){
dataSourceTransactionManager.commit(transaction);
}
/**
* 回滚
* @param transaction
*/
public void rollback(TransactionStatus transaction){
dataSourceTransactionManager.rollback(transaction);
}
}
Aop切面类
package com.qf;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
@Component
@Aspect
public class ExTransationAop {
@Autowired
private TransactionalUtils transactionalUtils;
@Around(value = "@annotation(com.qf.ExTransational)")
public Object reflect(ProceedingJoinPoint joinPoint){
TransactionStatus begin =null;
try {
begin = transactionalUtils.begin();
Object result = joinPoint.proceed();
transactionalUtils.commit(begin);
return result;
} catch (Throwable throwable) {
if (begin!=null){
transactionalUtils.rollback(begin);
}
throwable.printStackTrace();
}
return null;
}
}
最终效果
@ExTransational
public void insertUser() {
user user=new user(new Date(),"place",new Date());
userDao.insert(user);
int i=1/0;
}
