代理模式:
代理模式也是对开闭原则的一种实现,在不动源代码的情况下对功能扩展,通过代理对象 对目标对象的封装,很好的隐藏了目标对象,并对原功能进行了一次售前售后工作; spring aop 就是很典型的代理模式
静态代理模式:
// 目标对象和代理对象实现同一个接口 interface Interface01{ void fun01(); } // 目标对象 class TargetClass implements Interface01{ @Override public void fun01() { System.out.println("执行目标对象函数"); } } // 代理对象 class ProxyClass implements Interface01{ // 目标对象 private TargetClass targetClass ; // 有参构造器(传入一个目标对象的实例) public ProxyClass(TargetClass targetClass) { this.targetClass = targetClass; } // 执行方法 @Override public void fun01() { System.out.println("执行前***"); targetClass.fun01(); System.out.println("执行后***"); } }
动态代理:
由于静态代理每次都需要一个代理类,所以出现了动态代理,动态创建代理类
j'd'k 支持的动态代理: jdk的动态代理是基于接口的,要求目标类必须实现一个接口,但实际上并不是所有的类都有接口
public class TestDynamicProxy {
public static void main(String[] args) {
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(new TargetDncymicClass());
// 获取代理对象
Interface02 proxy = (Interface02) myInvocationHandler.getProxy();
proxy.fun02();
}
}
// 接口
interface Interface02{
void fun02();
}
// 目标类
class TargetDncymicClass implements Interface02{
@Override
public void fun02() {
System.out.println("TargetDncymicClass...");
}
}
// invocationHandler
class MyInvocationHandler implements InvocationHandler{
private Object target;
// 传入目标对象
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行前。。");
// 执行目标方法
Object object = method.invoke(target, args);
System.out.println("执行后。。");
return object;
}
// 获取生成的代理对象
public Object getProxy() {
// 参数1 类加载器,参数2 目标类的所有实现接口, 参数3 InvocationHandler
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
}
Cglib :
cglib实现的动态代理,不要求目标类实现接口,底层采用asm字节码生成代理类的字节码
// 定义目标类
class TargetCglibClass{
// 目标方法
public void test() {
System.out.println("TargetCglibClass...");
}
// methodInterceptor 方法拦截器
class MyMethodInterceptor implements MethodInterceptor{
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("执行前。。");
// 执行目标方法
Object object = methodProxy.invokeSuper(o, objects);
System.out.println("执行后。。");
return object;
}
}
//测试
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TargetCglibClass.class);
enhancer.setCallback(new MyMethodInterceptor());
TargetCglibClass o = (TargetCglibClass) enhancer.create();
o.test();
}
jdk和cglib动态代理实现的区别
1、jdk动态代理生成的代理类和委托类实现了相同的接口;
2、cglib动态代理中生成的字节码更加复杂,生成的代理类是委托类的子类,且不能处理被final关键字修饰的方法;
3、jdk采用反射机制调用委托类的方法,cglib采用类似索引的方式直接调用委托类方法;