一、代理模式 - 静态代理
代理模式本质是为了对原有逻辑的增强。
静态代理如下:
- 代理类和被代理类实现相同接口
- 在代理类中注入被代理类作为属性,在代理类中的方法调用被代理类的方法,就可在不修改被代理类的前提下对代码功能增强。
案例:
interface UserManager {
void add(String name,int age);
void find(String name);
}
//被代理类
public class UserManagerImpl implements UserManager{
@Override
public void add(String name, int age) {
System.out.println("UserManagerImpl.add()");
}
@Override
public void find(String name) {
System.out.println("UserManagerImpl.find()");
}
}
//代理类
public class UserManagerImplProxy implements UserManager {
//将被代理类设置为属性
private UserManagerImpl userManagerImpl;
//初始化被代理类
public UserManagerImplProxy(UserManagerImpl userManagerImpl){
this.userManagerImpl = userManagerImpl;
}
@Override //对代码增强
public void add(String name, int age) {
System.out.println("日志记录开始....");
userManagerImpl.add(name,age);
System.out.println("日志记录结束....");
}
@Override //对代码增强
public void find(String name) {
System.out.println("日志记录开始....");
userManagerImpl.find(name);
System.out.println("日志记录结束....");
}
}
//测试代码:
UserManager usermanager = new UserManagerImplProxy(new UserManagerImpl());
usermanager.add("张三",20);
二、代理模式 - 动态代理 - JDK代理 - 基于接口实现
通过java提供的java.lang.reflect.Proxy来动态生成代理类,从而简化代码。
public class TestProxy{
UserManagerImpl ui = new UserManagerImpl();
@Test
public void test01(){
// object:生成的代理实例
Object object = Proxy.newProxyInstance(
UserManagerImpl.class.getClassLoader(), //被代理着的类加载器
UserManagerImpl.class.getInterfaces(), //被代理者的接口有哪些
new InvocationHandler() { //调用处理程序接口,由代理实例来回调
/**
* 代理实例在调用目标方法时,最终执行该方法
* @param proxy 代理实例本身
* @param method 被代理者的目标方法对象
* @param args 被代理者的目标方法参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("日志记录开始....");
Object result = method.invoke(ui,args);
System.out.println("日志记录结束....");
return result; //result:目标方法的返回值
}
}
);
UserManager um = (UserManager) object;
um.add("测试1",11);
um.find("测试2");
}
}
这种方式我们称之为JDK代理,缺点是如果被代理者有自我拓展的方法(不是来自于接口的),那么代理后是无法调用这些方法的。必须保证,代理者和被代理者实现统一的接口,代理后只能调用接口中已有的方法。
三、代理模式 - 动态代理 - CGLIB代理 - 基于继承实现(代理者是被代理者的子类 )
由于cglib动态代理不是jdk提供,但是spring-core中已经集成了,所以不需要额外导包。
public class TestCGLIBProxy {
UserManagerImpl umi = new UserManagerImpl();
@Test
public void test01(){
//1.创建增强器对象
Enhancer enhancer = new Enhancer();
//2.设置接口(不是必须)
enhancer.setInterfaces(umi.getClass().getInterfaces());
//3.设置代理者的父类
enhancer.setSuperclass(umi.getClass());
//4.设置回调
enhancer.setCallback(new MethodInterceptor() {
/**
* @param o 代理者
* @param method 正在调用的方法
* @param objects 正在调用的方法参数
* @param methodProxy 方法代理对象
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("记录日志前...");
Object result = method.invoke(umi, objects);
System.out.println("记录日志后...");
return result;
}
});
//5.创建代理对象
Object obj = enhancer.create();
//6.调用
UserManagerImpl proxy = (UserManagerImpl)obj;
proxy.find("x");
}
}
好处是:因为是继承关系(父类:被代理者,子类:代理者),所以被代理者自我拓展的方法也可以被代理者调用。