解析动态代理模式与跟自定义注解配合使用以及事务注解原理

来源:互联网 发布:中国小镇 知乎 编辑:程序博客网 时间:2024/06/05 10:15

动态代理:用来修改已经具有的对象的方法,控制方法是否执行,或在方法执行之前和执行之后做一些额外的操作

Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);

loader -- 类加载器
interfaces -- 指定代理对象实现哪些接口,通常代理对象要和被代理对象实现相同的接口,从而保证和被代理者具有相同的方法
InvocationHandler 
-- 处理器对象,当调用代理对象的任何方法时,都会导致此对象中的invoke方法执行,在这个方法中可以编写是否允许方法执行,以及在方法执行之前和之后做那些额外的操作
{
Object invoke(Object proxy,   Method method,  Object[] args)
proxy -- 代理者对象
method -- 当前调用到的方法
args -- 方法的参数
返回值 -- 就是这个方法要返回什么



}


1.加载配置文件,用于程序解耦

config.properties 配置文件如下几行:

UserDao=com.itheima.dao.UserDaoImpl
UserService=com.itheima.service.UserServiceImpl
ProdDao=com.itheima.dao.ProdDaoImpl
ProdService=com.itheima.service.ProdServiceImpl
OrderService=com.itheima.service.OrderServiceImpl
OrderDao=com.itheima.dao.OrderDaoImpl


private static BasicFactory factory = new BasicFactory();
private static Properties prop = null;
private BasicFactory(){}
static{
try {
prop = new Properties();
prop.load(new FileReader(BasicFactory.class.getClassLoader().getResource("config.properties").getPath()));  // 读取配置文件
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}


2.解析,模仿注解事务原理

/**
* 获取Service的方法
*/
public <T extends Service> T getService(Class<T> clazz){
try{
//--根据配置文件创建具体的Service
String infName = clazz.getSimpleName(); //获取简单类名 单单是名称
String implName = prop.getProperty(infName); //  获取类名对应的实现类 从配置文件中读取
final T service = (T) Class.forName(implName).newInstance();

//--为了实现AOP,生成service代理,根据注解确定在Service方法执行之前和之后做一些操作,比如:事务管理/记录日志/细粒度权限控制....
T proxyService =  (T) Proxy.newProxyInstance(service.getClass().getClassLoader(), service.getClass().getInterfaces()
, new InvocationHandler(){

//根据注解控制事务
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);
}
}

阅读全文
0 0
原创粉丝点击