在web经典三层架构中,写代码的时候,为了完成事务的控制,需要把Connection从Service层传到Dao层,这就增加了Service层和Dao层的耦合.违背了经典三层架构的设计思想!
所以在开发的时候,可以使用一个注解.来完成对事务的控制,对Service层和Dao层进行解耦.
在java中提供了原生注解,常用的三种有:
@Override:限定重写父类方法,该注解只能用于方法
@Deprecated:用于表示某个程序元素(类,方法等)已过时
@SuppressWarnings:抑制编译器警告
自定义注解:
@interface 定义一个注解.
定义出来的注解可以被注解元素修饰,确定其基本的特性:
@Retention:只能用于修饰一个Annotation定义,用于指定该Annotation可以保留的域.Retention中有三种值:
RetentionPolicy.SOURCE:编译器直接丢弃这种策略的注解
RetentionPolicy.CLASS:编译器将注解记录在class文件.当运行java程序时,JVM不会保留注解.这是默认值
RetentionPolicy.RUNTIME:编译器将注解记录在class文件中.当运行java程序时,JVM会保留注解.程序可以通过反射获取该注解
@Target:指定注解用于修饰类中的哪个成员
@Documented:用于指定该元Annotation修饰的Annotation类将被javadoc工具提取成文档.
@Inherited:被它修饰的Annotation将具有继承性.如果某个类使用了被Ingerited修饰Annotation,则子类自动具有该注解
注解中还可以包含属性:
属性的定义类似于在接口中定义一个方法
String name();//定义一个name属性
String addr() default "xxx";//定义一个addr属性,并且这个属性的默认值是xxx
如果注解中只有一个属性并且名字为value,则在定义注解时可以直接写值而省略 value= 部分
反射注解:通过反射注解,来确定某个类方法属性上是否有注解从而控制程序的流转.
例如:如果想对程序进行事务控制,同时不希望Connection在Service层和Dao层进行传递而增加耦合,所以可以通过一个工具类来进行事务的管理,使用代理在事务之前做开启事务的操作,在事务之后做提交或者回滚的操作.但是同时也不是所有的操作都希望进行事务控制的,所以可以提前定义一个注解,通过判断类的身上有没有注解从而进行事务的控制.
//对事务进行控制的注解类
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)//使该注解保留到运行时
@Target(ElementType.METHOD)//注解使用的目标是方法
public @interface Tran {}
//减少因为事务控制,Service和Dao层的耦合
public <T extends Service> T getService(Class<T> clazz) {
try {
// --根据配置文件创建具体的service
String simName = clazz.getSimpleName();
String name = properties.getProperty(simName);
final T service = (T) Class.forName(name).newInstance();
// --为了实现AOP,生成service代理,根据注解确定在service方法执行之前和之后做一些事情,比如事务管理/记录日志/细粒度权限控制
@SuppressWarnings("unchecked")
T proxyService = (T) Proxy.newProxyInstance(service.getClass()
.getClassLoader(), service.getClass().getInterfaces(),
new InvocationHandler() {
@Override
// --根据注解控制事务
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if (method.isAnnotationPresent(Tran.class)) {// --如果有注解,则管理事务
try {
TransactionManager.startTran();// --开启事务
Object obj = method.invoke(service, args);// --真正执行方法
TransactionManager.commit();// --提交事务
return obj;
} catch (InvocationTargetException e) {
TransactionManager.rollback();// --回滚事务
throw new RuntimeException(e.getTargetException());
} catch (Exception e) {
TransactionManager.rollback();// --回滚事务
throw new RuntimeException(e);
} finally {
TransactionManager.release();// --释放资源
}
} else {// --如果没有注解,则不管理事务,直接执行方法
return method.invoke(service, args);
}
}
});
return proxyService;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}