代理模式的企业 (代理模式大全)

前言

代理模式是我们在工作中常用的一种设计模式,通过代理模式,我们可以很好地做到功能的分离,在用户无感知的情况下,在方法执行的前后增加一些操作,增强代码的功能

静态代理

先来看一个简单的例子

  • FindHouse
public interface FindHouse {

    /**
     * 找房子
     */
    void findHouse();
}
  • Agent
public class Agent implements FindHouse {

    private Person person;

    public Agent(Person person) {
        this.person = person;
    }

    @Override
    public void findHouse() {
        System.out.println("确定房源位置");
        person.findHouse();
        System.out.println("收款");
    }
}
  • Person
public class Person implements FindHouse {

    @Override
    public void findHouse() {
        System.out.println("找到房源");
    }
}

静态代理模式比较简单,通过静态,我们可以在不改变原先类的情况下,扩展类的功能,但是静态代理必须为每个被代理类手动的创建一个代理类,复用性太差

动态代理

JDK

  • DynamicLog
public class DynamicLog implements InvocationHandler {

    private Object obj;

    public DynamicLog(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开始调用方法");
        Stopwatch stopwatch = Stopwatch.createStarted();
        Object result = method.invoke(obj, args);
        System.out.println("方法调用结束,调用时长: " + stopwatch.elapsed(TimeUnit.MILLISECONDS));
        return result;
    }
}
  • IStudentService
public interface IStudentService {

    void save(Student student);

}
  • ProxyHelper
public class ProxyHelper {

    public static <T> T getProxy(Object object) {
        return (T) Proxy.newProxyInstance(object.getClass().getClassLoader(),
                object.getClass().getInterfaces(), new DynamicLog(object));
    }
}
  • Student
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student implements Serializable {

    private Long id;
    private String name;
    private Integer age;
}
  • StudentServiceImpl
public class StudentServiceImpl implements IStudentService {

    @Override
    public void save(Student student) {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("保存学生信息" + student);
    }
}

JDK动态代理是我们在工作中常用的一种代理模式,它会自动创建一个实现了被代理类接口的类,通过这个类,去调用InvocationHandler接口的invoke方法,我们就可以在调用invoke方法时,动态的给方法新增一些功能,以此来达到解耦的目的。

注意点:JDK动态代理的被代理类必须实现接口

CGLIB

  • DynamicLog
public class DynamicLog implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("开始执行方法");
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("方法执行结束");
        return result;
    }
}
  • ProxyHelper
public class ProxyHelper {

    public static <T> T createProxy(Class<T> clazz) {
        // 代理类class文件存入本地磁盘方便我们反编译查看源码
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(new DynamicLog());
        return (T) enhancer.create();
    }
}
  • StudentService
public class StudentService {

    public void saveStudent(String name) {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("保存学生信息");
    }
}

JAVASIS

  • JavassistProxyFactory
public class JavassistProxyFactory {

    public static <T> T getProxy(Class<T> clazz) throws IllegalAccessException, InstantiationException {
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setSuperclass(clazz);
        proxyFactory.setFilter(new MethodFilter() {
            public boolean isHandled(Method m) {
                // ignore finalize()
                return !m.getName().equals("finalize");
            }
        });

        Class<?> c = proxyFactory.createClass();
        MethodHandler mi = new MethodHandler() {
            public Object invoke(Object self, Method m, Method proceed,
                                 Object[] args) throws Throwable {
                System.out.println("开始执行方法");
//                System.out.println("method name: " + m.getName() + " exec");
                Object result = proceed.invoke(self, args);  // execute the original method.
                System.out.println("执行方法结束");
                return result;
            }
        };
        Object proxy = c.newInstance();
        ((Proxy) proxy).setHandler(mi);
        return (T) proxy;
    }
}