设计模式 -- (代理模式)

代理模式:

         代理模式也是对开闭原则的一种实现,在不动源代码的情况下对功能扩展,通过代理对象 对目标对象的封装,很好的隐藏了目标对象,并对原功能进行了一次售前售后工作; 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采用类似索引的方式直接调用委托类方法;

猜你喜欢

转载自blog.csdn.net/xiaodujava/article/details/88866292