第一章:什么是动态代理
当想要给某个类的某个方法,添加一些额外的处理。可以创建一个代理类,在执行这个方法前后执行想要添加的逻辑。如果在程序运行前就定义好这个代理类,叫做静态代理;如果在程序运行时创建这个类,叫做动态代理。
第二章:使用JDK动态代理实现
第一步:创建需要代理的接口
/**
* 该类是被代理类的接口类,JDK的代理要求被代理类基于统一的接口
*/
public interface Service {
//add 方法
void add();
//update 方法
void update();
}
|
第二步:创建目标类,实现这个接口
/**
* 实现Service接口的A类
*/
public class AServiceImp implements Service {
public void add() {
System.out.println("=======>>add from A");
}
public void update() {
System.out.println("=======>>update from A");
}
}
|
第三步:实现InvocationHandler 接口,实现invoke方法,处理代理逻辑和执行目标方法
/**
* 实现InvocationHandler 目标类方法的执行就是有method.invoke()完成的
* 在 invoke方法中加入切面逻辑
*/
public class ServiceInvocationHandler implements InvocationHandler {
private Object target;
ServiceInvocationHandler() {
super();
}
ServiceInvocationHandler(Object target) {
super();
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//程序执行前逻辑
System.out.println("before------------");
//程序执行
Object result = method.invoke(target, args);
//程序执行后逻辑
System.out.println("after-------------");
return result;
}
}
|
第四步:测试
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
Service serviceA = new AServiceImp();
ServiceInvocationHandler handeler = new ServiceInvocationHandler(serviceA);
Service serviceProxy = (Service) Proxy.newProxyInstance(serviceA.getClass().getClassLoader(),
serviceA.getClass().getInterfaces(), handeler);
serviceProxy.add();
serviceProxy.update();
}
}
|
控制台输出:
before------------
=======>>add from A
after-------------
before------------
=======>>update from A
after-------------
|
第三章,使用cglib进行动态代理
第一步:引入jar包,cglib主要使用ASM框架操作字节码
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.5</version>
</dependency>
|
第二步:创建目标类,cglib不需要同一的接口
/**
* 需要被代理的类,cglib不需要定义目标类的同一接口
*/
public class Service {
//模拟的add方法
public void add() {
System.out.println("add-------");
}
}
|
第三步:创建代理类,实现MethodInterceptor接口。
/**
* Service 的代理类,实现MethodInterceptor接口
* 在intercept中加入切面逻辑
* 目标执行预计语句是
*/
public class ServiceProxy implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
//执行前逻辑
System.out.println("before--------->");
//程序执行
Object result = proxy.invokeSuper(obj, args);
//执行后逻辑
System.out.println("after---------->");
return result;
}
}
|
第四步:创建工厂类,产生代理实例
/**
* 代理对象的工厂类,在这里完成切面的封装
*/
public class ProxyFactory {
public static Service getInstance(ServiceProxy proxy) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Service.class);
enhancer.setCallback(proxy);
return (Service) enhancer.create();
}
}
|
第五步:测试
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
ServiceProxy proxy = new ServiceProxy();
Service service = ProxyFactory.getInstance(proxy);
service.add();
//新生成的类是Service的子类
System.out.println(service.getClass().getSimpleName());
System.out.println(( service.getClass().getSuperclass().getSimpleName()));
}
}
|
控制台输出:
before--------->
add-------
after---------->
Service$$EnhancerByCGLIB$$10ccd71e
Service
|
第四章:总结
使用JDK和cglib都可以通过操作Java字节码实现动态代理,JDK动态代理使用接口操作字节码,cglib在ASM框架上进行实现,性能上cglib高于jdk的(没有验证)。JDK动态代理中,被代理类需要有统一的接口,代理类是接口的实现;在cglib的动态代理中,被代理类不需要实现统一的接口,代理类是被代理类的子类。
在Spring AOP中包含了这两种动态代理方法,具体的调用根据被代理类的是否有统一接口决定。