今天看书看到jdk和CGLIB动态代理模式,回想了下上学期学的代理模式,感觉大有不同,困惑下找了找资料才了解到java的这三种代理模式,一篇很好的博客博客链接,自己也敲了敲算是明白了。
一、静态代理模式
这个就是学23种设计模式接触的那种了,特点是 代理者和被代理者实现同一个接口的情况下,代理者类之中同时拥有一个被代理者对象,这样子的话被代理者类中实现具体操作,代理者中实现代理逻辑,也就是通过这个对象实现被代理者应做的事情。
代码如下:
接口
package ssm.proxy;
public interface Hello {
public void sayHello(String str);
}
接口实现类(被代理者):
package ssm.proxy;
public class HelloImpl implements Hello {
@Override
public void sayHello(String str) {
System.out.println("hello " + str);
}
}
代理者:
package ssm.proxy;
public class ProxyExample implements Hello {
/**
* 普通代理模式,代理者和被代理者同时继承接口
* 同时, 代理者类 拥有 被代理者的 对象
* 代理操作
*/
private Hello target = null;
//1. 建立代理对象和真实对象的关系
public ProxyExample(Hello target) {
this.target = target;
}
/**
* 2. 实现代理逻辑
*/
@Override
public void sayHello(String str) {
System.out.println("before1 代理逻辑");
target.sayHello(str);
System.out.println("after1 代理逻辑");
}
}
测试类(main):
package ssm.proxy;
public class TestMain {
public static void main(String[] args){
test1();
//test2();
//test3();
}
public static void test1(){
Hello target = new HelloImpl();
Hello proxy = new ProxyExample(target);
proxy.sayHello("普通静态代理模式");
}
}
测试结果:
before1 代理逻辑
hello 普通静态代理模式
after1 代理逻辑
Process finished with exit code 0
二、jdk动态代理
jdk动态代理同静态一样,需要借助同一个接口才能产生代理对象,这里也使用上面接口。
在这里我理解的:这里的JdkProxyExample类,虽然是很像上面的ProxyExample类,但是他们本质是有很大差别的了,JDKProxyExample并不是一个被代理者类,而是相当于一个工具类。
这个工具类的作用,就是代理模式最重要的两个步骤:1、建立代理对象和真实对象的关系; 2、实现代理逻辑。
而代理者,就应该是遵循最基本的原理,和代理者实现同一个接口,虽然没有直接写它的类,但是在测试中,我们能够通过工具类得到它。
代码如下:
jdk代理:
package ssm.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxyExample implements InvocationHandler {
//真实对象
private Object target = null;
/**
*
* @param target 真实对象
*/
public JdkProxyExample(Object target) {
this.target = target;
}
/**
* 1. 建立代理对象和真实对象的代理关系
*
* 这个函数是为了得到代理对象
* @return 代理对象
*/
public Object getProxyInstance(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
/**
* 2. 代理方法逻辑
* @param proxy 代理对象
* @param method 当前调度方法
* @param args 当前方法参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before2 代理逻辑");
//相当于 调用 target.sayHello()
Object obj = method.invoke(target, args);
System.out.println("after2 代理逻辑");
return obj;
}
}
测试部分(testMain类中):
public static void test2(){
//被代理者
Hello target = new HelloImpl();
JdkProxyExample jdkPE = new JdkProxyExample(target);
//代理者
Hello proxy = (Hello) jdkPE.getProxyInstance();
/*
在这一句的时候
运行了 invoke()函数 (继承的)
这里的proxy, 并不是简单的Hello接口实现
*/
proxy.sayHello("JDK动态代理");
}
测试结果:
before2 代理逻辑
hello JDK动态代理
after2 代理逻辑
Process finished with exit code 0
三、CGLIB动态代理
CGLIB动态代理,与前两个不同之处在于:被代理者不需要有接口,只是一个单纯的类就可以代理。所以我新建了个类以体现出来
CglibProxyExample类和上面JdkProxyExample类都一样是一个工具类。
代码如下:
被代理者:
package ssm.proxy;
public class HelloCglib {
public void print(){
System.out.println("CGLIB代理模式");
}
}
CGLIB代理:
package ssm.proxy;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyExample implements MethodInterceptor {
/**
* 1. 生成CGLIB 代理对象
* @param cls
* @return
*/
public Object getProxy(Class cls){
//得到 工具类对象
Enhancer enhancer = new Enhancer();
//设置 父类
enhancer.setSuperclass(cls);
//设置 代理逻辑对象 为 当前对象
enhancer.setCallback((Callback) this);
//返回 代理对象
return enhancer.create();
}
/**
* 2. 代理逻辑方法
* @param proxy 代理对象
* @param method 方法
* @param objects 方法参数
* @param methodProxy 代理逻辑返回
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object proxy, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
System.out.println("before3 代理逻辑");
Object result = methodProxy.invokeSuper(proxy, objects);
System.out.println("after3 代理逻辑");
return result;
}
}
测试部分(testMain类中):
public static void test3(){
//被代理者
HelloCglib target = new HelloCglib();
CglibProxyExample cglibPE = new CglibProxyExample();
//被代理者
HelloCglib proxy = (HelloCglib) cglibPE.getProxy(target.getClass());
/*
在这一句的时候
运行了 intercept()函数 (继承的)
这里的proxy, 并不是简单的HelloCglib对象
*/
proxy.print();
}
测试结果:
before3 代理逻辑
CGLIB代理模式
after3 代理逻辑
Process finished with exit code 0