生活中实例

中介、黄牛、媒人、经纪人、快递... (关注过程)

特点

  1. 角色:执行者、被代理人
  2. 对被代理人来说,这件事是一定要做的,但是自己又不想做或没时间,找代理
  3. 需要获取到被代理人的个人资料

JDK和CGLib比较

  1. JDK动态代理只能对实现了接口的类生成代理,而不能针对类
  2. CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,并覆盖其中方法实现增强,但是因为采用的是继承,所以该类或方法最好不要声明成final,对于final类或方法,是无法继承的。
  3. ......

JDK动态代理代码示例

package com.proxy.jdk;

public interface Person {

    void save(String name);

    void update(int id);
}
package com.proxy.jdk;

public class Somnus implements Person {
    private String name;

    public Somnus() {

    }

    public Somnus(String name) {
        this.name = name;
    }

    @Override
    public void save(String name) {
        System.out.println("执行了save()方法");
    }

    @Override
    public void update(int id) {
        System.out.println("执行了update()方法");
    }

    public String getName() {
        return name;
    }
}

package com.proxy.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JDKProxy implements InvocationHandler {

    private Object targetObject;

    public Object createTartetInstance(Object targetObject) {
        this.targetObject = targetObject;
        return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(), this.targetObject.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置通知...");
        Object result = null;
        Somnus somnus = (Somnus) this.targetObject;
        if (somnus.getName() != null) {
            try {
                result = method.invoke(this.targetObject, args);
                System.out.println("后置通知...");
            } catch (Exception e) {
                System.out.println("例外通知...");
            } finally {
                System.out.println("最终通知...");
            }
        }
        return result;
    }
}

package com.proxy.jdk;

public class UnitTest {
    public static void main(String[] args) {
        Person person = (Person) new JDKProxy().createTartetInstance(new Somnus("yyyy"));
        person.save("xxxx");
    }
}

前置通知...
----------------------------分割线--------------------------------
前置通知...
执行了save()方法
后置通知...
最终通知...

CGLib动态代理代码示例

package com.proxy.cglib;

public class Somnus {
    private String name;

    public Somnus() {

    }

    public Somnus(String name) {
        this.name = name;
    }

    public void save(String name) {
        System.out.println("执行了save()方法");
    }

    public void update(int id) {
        System.out.println("执行了update()方法");
    }

    public String getName() {
        return name;
    }
}

package com.proxy.cglib;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CGLibProxy implements MethodInterceptor {

    public Object createTartetInstance(Class clazz) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("CGLib前置通知...");
        Object result = null;
        try {
            result = methodProxy.invokeSuper(o, objects);
            System.out.println("CGLib后置通知...");
        } catch (Exception e) {
            System.out.println("CGLib例外通知...");
        } finally {
            System.out.println("CGLib最终通知...");
        }
        return result;
    }
}

package com.proxy.cglib;

public class UnitTest {
    public static void main(String[] args) {
        Somnus somnus = (Somnus) new CGLibProxy().createTartetInstance(Somnus.class);
        somnus.save("xxxx");
    }
}
前置通知...
----------------------------分割线--------------------------------
前置通知...
执行了save()方法
后置通知...
最终通知...