一:JDK动态代理
JDK动态代理所用到的代理类在程序调用到代理类对象时才由JVM真正创建,JVM根据传进来的 业务实现类对象 以及 方法名 ,动态地创建了一个代理类的class文件并被字节码引擎执行,然后通过该代理类对象进行方法调用。
案例
1、定义业务接口以及实现类
package com.yjc.jdkproxy;
public interface DoSomeService {
void doSome();
}
-------------------------------------------
package com.yjc.jdkproxy;
public class DoSomeServiceImpl implements DoSomeService {
@Override
public void doSome() {
System.out.println("doSome++++++++++++++++++==");
}
}
2.调用管理接口InvocationHandler 创建动态代理类
package com.yjc.jdkproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class DoSomeHandler implements InvocationHandler { //这其实业务实现类对象,用来调用具体的业务方法 private Object target; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before----------------------------");
//调用真正的业务方法 Object invoke = method.invoke(target, args); System.out.println("after---------------------------"); return invoke; } public DoSomeHandler(Object target) { this.target = target;//接收业务实现类对象参数 } public DoSomeHandler() { } }
测试方法
package com.yjc.jdkproxy; import sun.misc.ProxyGenerator; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Proxy; public class JdkProxyTest { public static void main(String[] args) throws IOException { DoSomeService doSomeService=new DoSomeServiceImpl();
//通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用
//创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类
DoSomeService o = (DoSomeService)Proxy.newProxyInstance(doSomeService.getClass().getClassLoader(), new Class[]{DoSomeService.class}, new DoSomeHandler(doSomeService)); //调用目标函数
o.doSome();
//将内存中代理的类生成到本地 byte[] $proxy0s = ProxyGenerator.generateProxyClass("$proxy0", new Class[]{DoSomeService.class}); FileOutputStream fos=new FileOutputStream("F:/$proxy0.class"); fos.write($proxy0s); fos.flush(); fos.close(); } }
二:CGLIB动态代理
cglib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理。因为采用的是继承,所以不能对final修饰的类进行代理。
cglib和jdk动态代理的区别就是,cglib无需业务接口也可以实现动态代理,而jdk是在业务接口的基础上进行实现的,没有接口不行。cglib也需要项目对cglib的支持,需要引入依赖
业务类
package com.yjc.cglibproxy;
public class DoSomeServiceImpl {
public void doSome() {
System.out.println("doSome++++++++++++++++++==");
}
}
代理类
package com.yjc.cglibproxy;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DoSomeHandler implements MethodInterceptor {
//目标对象
private Object target;
public DoSomeHandler(Object target) {
this.target = target;
}
public DoSomeHandler() {
}
/**
*
* 方法描述 当对基于代理的方法回调时,在调用原方法之前会调用该方法
* 拦截对目标方法的调用
*
* @param obj 代理对象
* @param method 拦截的方法
* @param args 拦截的方法的参数
* @param proxy 代理
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before==========================");
Object invoke = method.invoke(target, objects);
System.out.println("after============================");
return invoke;
}
}
测试类
package com.yjc.cglibproxy;
import net.sf.cglib.proxy.Enhancer;
public class CglibProxyTest {
public static void main(String[] args) {
Enhancer enhancer=new Enhancer();
// 设置目标对象的Class
enhancer.setSuperclass(DoSomeServiceImpl.class);
// 设置回调操作,相当于InvocationHandler
enhancer.setCallback(new DoSomeHandler(new DoSomeServiceImpl()));
DoSomeServiceImpl o =(DoSomeServiceImpl) enhancer.create();
o.doSome();
} }