前言
代理模式是我们在工作中常用的一种设计模式,通过代理模式,我们可以很好地做到功能的分离,在用户无感知的情况下,在方法执行的前后增加一些操作,增强代码的功能
静态代理
先来看一个简单的例子
- 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;
}
}