代理设计模式:
原有的业务不做任何修改,添加额外的功能
分为静态代理和动态代理
动态代理:
jdk动态代理
cglib动态代理
1.静态代理:
1)写原有的业务功能接口和类
2)写新的业务功能类
3)静态代理类
通过此类把原有的业务和新的业务耦合在一起
静态代理类必须实现老的业务的接口,使得静态代理类功能不少于原有业务
有多少个业务就有多少个静态代理类
静态代理类在编译期间就已经确定了原有业务和新功能的耦合模型
4)写测试类:检测新的业务和老的业务是否已经耦合
静态代理总结:
1.没有修改原有代码的业务功能,没有破坏开闭原则
2.有新的业务功能,且新功能业务类和原有业务类都独立,遵循单一职责
3.新建了一个静态代理类,把原有的业务和新功能的业务耦合在一起,不是单一职责原则
a.要求静态代理类实现业务接口,保证业务完整性
b.有多少个业务就有多少个静态代理类
c.静态代理类不满足单一职责,在静态代理类中明显耦合了原有业务和新业务
4.静态代理类在编译期间就已经确定了原有业务和新功能业务的耦合模型
2.动态代理:
-JDK动态代理:
1)写原有的业务功能接口和类
2)写新的业务功能类
3)jdk动态代理类
-创建JDKProxy类
public class JDKProxy {
/**
* 此方法用来生产代理对象
* @param targetObject 目标对象(原有的目标对象)
* @return 代理对象
* 通过目标对象生产代理对象,利用jdk工具生成
*/
public static Object getProxyObject(Object targetObject) {
Object proxyObject=null;
/**
* Proxy类是jdk类库中自带的类
* 其中newProxyInstance方法数一个静态方法
* 此方法有三个参数
*
* 参数一:类加载器,任意类都可以获取到类加载器,只能获取,本质是用来定位类路径的
* 参数二:Class[]数组,获取目标对象所对应的类的所有接口
* 要求jdk动态代理,目标类必须有接口,否则无法用jdk生成代理类对象
* 代理对象和目标对象之间是兄弟关系,以为代理类和目标类有共同的接口
* 参数三:必须是InvocationHandler接口的对象
*
* 此newProxyInstance方法本质就是先动态创建出代理类,然后根据代理类创建代理对象
* 生成代理类是一个字节数组,存储在内存中
* 通过这个字节数组的代理类,来创建出代理对象
* 且此代理类一定也要实现老的业务接口,以保证业务的完整性
* 在代理类中重写了老的业务接口的方法
* 在重写的业务方法中调用了InvocationHandler的invoke方法
*/
proxyObject=Proxy.newProxyInstance(
targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
new TransactionHandler(targetObject));
return proxyObject;
}
}
-创建TransactionHandler实现InvocationHandler接口
把新的业务和老的业务耦合
public class TransactionHandler implements InvocationHandler {
//targetObject是老的业务对象
private Object targetObject;
public TransactionHandler(Object targetObject) {
this.targetObject = targetObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object returnValue=null;
//创建新的业务对象
TransactionManager transactionManager=new TransactionManager();
try {
//前置通知功能
transactionManager.begin();
//用老的业务对象调用老的业务方法
returnValue=method.invoke(targetObject, args);
//事务提交
transactionManager.commit();
} catch (Exception e) {
//异常回滚
transactionManager.rollback();
e.printStackTrace();
}finally {
//最终通知功能
}
return returnValue;
}
}
4)创建测试类查看新旧业务是否已经耦合
-CGLIB动态代理:
1)写原有的业务功能接口和类
2)写新的业务功能类
3)cglib动态代理类
-创建CGLIBProxy类
public class CGLIBProxy {
/**
* 此方法是用来生成代理对象
* @param targetObject 目标对象(原有的目标对象)
* @return 代理对象
* 通过目标对象生产出代理对象,利用cglib工具生成
*/
public static Object getProxyObject(Object targetObject) {
Object proxyObject=null;
/**
* 此目标类一定不能是final
* cglib生成代理类是目标类的子类,变相约束代理的功能的完整性
* 要求必须实现MethodInterceptor接口中的intercept方法
* 在intercept方法中耦合老的业务和新的业务
*/
//Enhancer:加强,增强
Enhancer enhancer=new Enhancer();
//此语句可以不用写,即用cglib生成代理类,目标类有无接口皆可,但目标一定不能是final
enhancer.setInterfaces(targetObject.getClass().getInterfaces());
//设置代理类的父类(此语句必须有)
enhancer.setSuperclass(targetObject.getClass());
//设置回调,用于回调耦合的方法(intercept方法,在MethodInterCept接口中)
enhancer.setCallback(new TransactionHandler(targetObject));
//创建cglib的代理对象,其实是用asm创建的代理类
proxyObject=enhancer.create();
return proxyObject;
}
}
-创建TransactionHandler类实现MethodInterceptor接口
public class TransactionHandler implements MethodInterceptor {
//targetObject是老的业务对象
private Object targetObject;
public TransactionHandler(Object targetObject) {
this.targetObject = targetObject;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object returnValue=null;
//创建新的业务对象
TransactionManager transactionManager=new TransactionManager();
try {
transactionManager.begin();
//用老的业务对象调用老的业务方法(二者选其一)
//Method是java.reflect包的类
//MethodProxy是cglib工具包对Method的一个封装
//returnValue=method.invoke(targetObject, args);
returnValue=methodProxy.invoke(targetObject, args);
transactionManager.commit();
} catch (Exception e) {
transactionManager.rollback();
e.printStackTrace();
}finally {
}
return returnValue;
}
}
4)创建测试类查看新旧业务是否已经耦合
动态代理总结:
1.原有的业务功能没有被修改,新的业务功能也添加了,遵守了开闭原则
2.原有的业务类,新功能的业务类都是独立类,遵守了单一职责
3.静态代理类是由程序员创建的,动态代理类是由根据创建爱的(jdk,cglib)
4.每一个业务对应一个动态代理类,运行期间确定代理类,开发效率高,执行效率低
5.动态代理有缓存,存储代理类字节码,效率也不会太低
6.动态代理类用动态代理类回调指定接口的方法,然后用该接口的子实现耦合功能
7.通过jdk或cglib生成代理类,通过代理类实例化代理对象
3.动态代理jdk和cglib的区别
jdk动态代理:
1.业务类必须有接口
2.必须实现InvocationHandler接口,在接口的子实现中耦合原有的业务和新业务
3.代理类和业务类是兄弟关系,同属于一个接口
4.用动态代理jdk创建代理,创建代理快,执行代理慢
cglib代理:
1.业务类有无接口皆可
2.必须实现MethodInterceptor接口,在接口的自实现中耦合原有业务和新业务
3.代理类和业务类是父子关系,业务类是长辈,代理类是子类
4.用asm和cglib创建代理类,创建慢,执行快
5.业务类不用final修饰