代理模式:
为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用, 其特征是代理类与委托类有同样的接口。
主要角色:
代码:
<1.主题接口
package exercise.DynamicProxyExercise; /** * Created by ibm on 2017/6/19. */ public interface Subject { void method(); }
package exercise.DynamicProxyExercise.impl; import exercise.DynamicProxyExercise.Subject; /** * Created by ibm on 2017/6/19. */ public class RealSubject implements Subject { @Override public void method() { System.out.println("subject method"); } }
<3.jdk实现的动态代理
package exercise.DynamicProxyExercise.proxyImpl; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * Created by ibm on 2017/6/19. */ public class JDKProxy implements InvocationHandler { // 这个就是我们要代理的真实对象 private Object subject; // 构造方法,给我们要代理的真实对象赋初值 public JDKProxy(Object subject) { this.subject = subject; } @Override public Object invoke(Object object, Method method, Object[] args) throws Throwable { // 在代理真实对象前我们可以添加一些自己的操作 System.out.println("jdk before ---------------------->"); System.out.println("Method:" + method); // 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用 method.invoke(subject, args); // 在代理真实对象后我们也可以添加一些自己的操作 System.out.println("jdc after ---------------------->"); return null; } }
cglib实现的动态代理
package exercise.DynamicProxyExercise.proxyImpl; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * Created by ibm on 2017/6/19. */ public class CglibProxy implements MethodInterceptor { private Object targetObject;// CGLib需要代理的目标对象 public Object createProxyObject(Object obj) { this.targetObject = obj; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(obj.getClass()); enhancer.setCallback(this); Object proxyObj = enhancer.create(); return proxyObj;// 返回代理对象 } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object obj = null; System.out.println("cglib before ---------------------------------->"); System.out.println("Method:" + method); obj = method.invoke(targetObject, args); System.out.println("cglib after ---------------------------------->"); return obj; } }
<4.客户端测试代码
package exercise.DynamicProxyExercise.client; import exercise.DynamicProxyExercise.Subject; import exercise.DynamicProxyExercise.impl.RealSubject; import exercise.DynamicProxyExercise.proxyImpl.CglibProxy; import exercise.DynamicProxyExercise.proxyImpl.JDKProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; /** * Created by ibm on 2017/6/19. */ public class Client { public static void main(String[] args) { //代理的真实对象 Subject realSubject = new RealSubject(); //代理的真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的 InvocationHandler handler = new JDKProxy(realSubject); /* * 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数: * * 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象 * * 第二个参数realSubject.getClass().getInterfaces(), * 我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了 * (由此可见,spring中只有实现了接口的类,才会使用jdk提供给的动态代理) * * 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上 * * Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象, * 它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型, * 而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号。 * */ Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject .getClass().getInterfaces(), handler); System.out.println(subject.getClass().getName()); subject.method(); System.out.println("\n\n"); Subject subject1 = (Subject) new CglibProxy().createProxyObject(realSubject); System.out.println(subject1.getClass().getName()); subject1.method(); } }