Java进阶(八)动态代理
代理模式
为其他对象提供一个代理以控制对某个对象的访问。代理类和被代理类通常会存在关联关系(即持有被代理对象的引用),代理类本身不实现服务,而是通过调用被代理类中的方法来提供服务。
具体参考:设计模式(二)结构型模式
JDK动态代理
JDK动态代理采用字节重组,重新生成对象来替代原始对象,以达到动态代理的目的。JDK动态代理生成对象的步骤如下:
- 获取被代理对象的引用,并且获取它的所有接口,通过反射获取(实现InvocationHandler接口,重写invoke方法);
- JDK动态代理类重新生成一个新的类,同时新的类要实现被代理类的所有接口(Proxy.newProxyInstance);
- 编译生成新的.class文件,并加载到JVM中运行
实例验证
接口:
public interface Person { void study(String lesson); }
实现类:
public class Student implements Person { @Override public void study(String lesson) { System.out.println("Study " + lesson); } }
代理类:
1 public class JdkProxy implements InvocationHandler { 2 3 // 需要代理的目标对象 4 private Object target; 5 6 public Object getInstance(Object target) { 7 this.target = target; 8 Class<?> clazz = target.getClass(); 9 return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this); 10 } 11 12 @Override 13 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 14 before(); 15 Object obj = method.invoke(this.target, args); 16 after(); 17 return obj; 18 } 19 20 private void after() { 21 System.out.println("我要结束了"); 22 } 23 24 private void before() { 25 System.out.println("我要开始了"); 26 } 27 28 }
验证:
public class TestMain { public static void main(String[] args) { Person p = (Person) new JdkProxy().getInstance(new Student()); p.study("English"); } } -------------------------- 我要开始了 Study English 我要结束了
CGlib动态代理
JDK代理要求被代理的类必须实现接口,有很强的局限性。而CGLIB动态代理则没有此类强制性要求。简单的说,CGLIB会让生成的代理类继承被代理类,并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。在CGLIB底层,其实是借助了ASM这个非常强大的Java字节码生成框架。代理类对象是由Enhancer类创建的,Enhancer是CGLIB的字节码增强器,可以很方便的对类进行拓展。另外,CGlib需要额外引入jar包。
实例验证
实现类:
public class Student{ public void study(String lesson) { System.out.println("Study " + lesson); } }
代理类:
public class CglibProxy implements MethodInterceptor { public Object getInstance(Class<?> clazz) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { before(); Object object = proxy.invokeSuper(obj, args); after(); return object; } private void after() { System.out.println("我要结束了"); } private void before() { System.out.println("我要开始了"); } }
验证:
public class TestMain { public static void main(String[] args) { Student s = (Student) new CglibProxy().getInstance(Student.class); s.study("English"); } } ---------------------- 我要开始了 Study English 我要结束了

浙公网安备 33010602011771号