1、静态代理
由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
接口类:
package org.lazyzhong.test; public interface People { public void speak(); public void doWork(); }
?实现类:
package org.lazyzhong.test; public class Man implements People{ @Override public void speak() { System.out.println("I am man"); } @Override public void doWork() { System.out.println("I do work"); } }
?代理类:
package org.lazyzhong.test; public class PeopleProxy implements People{ private Man man; public PeopleProxy() { super(); } public PeopleProxy(Man man) { this.man = man; } @Override public void speak() { System.out.println("有请人类1/2的代表讲话。。。"); man.speak(); System.out.println("人类1/2的代表讲话完毕。。。"); } @Override public void doWork() { } }
?测试类:
People p=new PeopleProxy(new Man()); p.speak();
?输出:
有请人类1/2的代表讲话。。。
I am man
人类1/2的代表讲话完毕。。。
?
2、动态代理
在程序运行时,运用反射机制动态创建而成。
2.1 jdk动态代理
接口类,实现类和上面的一样。。。
代理类:
package org.lazyzhong.test; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MyProxy implements InvocationHandler{ private Object target; public Object bind(Object target){ this.target=target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //方法中的Proxy不是target,是虚拟的实现类。 Object result=null; System.out.println("事物开始"); result=method.invoke(target, args); System.out.println("事物结束"); return result; } }
?测试类:
MyProxy proxy=new MyProxy(); People p=(People)proxy.bind(new Man()); p.speak(); p.doWork();
?输出:
事物开始
I am man
事物结束
事物开始
I do work
事物结束
JDK动态代理中包含一个类和一个接口:?
InvocationHandler接口:?
public interface InvocationHandler {?
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;?
}?
参数说明:?
Object proxy:指被代理的对象。?
Method method:要调用的方法?
Object[] args:方法调用时所需要的参数?
可以将InvocationHandler接口的子类想象成一个代理的最终操作类,替换掉ProxySubject。?
Proxy类:?
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法:?
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)? throws IllegalArgumentException?
参数说明:?
ClassLoader loader:类加载器?
Class<?>[] interfaces:得到全部的接口?
InvocationHandler h:得到InvocationHandler接口的子类实例
?
2.2 cglib动态代理:注意cglib是否和asm.jar版本冲突..这里用的是cglib-2.1.95和asm-3.3
实现类:
package org.lazyzhong.test; public class Man{ //注意并没有实现接口 public void speak() { System.out.println("I am man"); } }
?代理类:
package org.lazyzhong.test; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class MyCGProxy implements MethodInterceptor{ private Object target; /** * 创建代理对象 * @param target * @return */ public Object getInstance(Object target){ this.target=target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); // 回调方法 enhancer.setCallback(this); // 创建代理对象 return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("事物开始"); proxy.invokeSuper(obj, args); System.out.println("事物结束"); return null; } }
?测试:
MyCGProxy pro=new MyCGProxy(); Man man=(Man)pro.getInstance(new Man()); man.speak();
?输出:
事物开始
I am man
事物结束
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
?