这是我参与更文挑战的第8天,活动详情查看: 更文挑战
介绍
动态代理主要用来做方法的增强,让你可以在不修改源码的情况下,增强一些方法,在方法执行前后做任何你想做的事情。动态代理是设计模式中代理模式的一种。
Spring 提供了两种方式来生成代理对象: JDKProxy 和 Cglib,具体使用哪种方式 生成由 AopProxyFactory 根据 AdvisedSupport 对象的配置来决定。 默认的策略是如果目标类是接口, 则使用 JDK 动态代理技术,否则使用 Cglib 来生成代理。
Java动态代理
Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:
(1)Interface InvocationHandler:该接口中仅定义了一个方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
-
proxy : 表示代理类
-
method : 表示被代理的方法
-
args : 该方法的参数数组 (2)Proxy:动态代理类
public static Object newProxyInstance(ClassLoader loader,
Class[<?>[]](url) interfaces,
InvocationHandler h)
这个静态方法返回一个代理类的实例
- loader 类加载器
- interfaces
- h : 实现实现InvocationHandler接口的类的实例 动态代理类是在运行时生成的class,在生成它时你必须提供一组interface给它,然后相当于这个类实现了这些 interface。然后就可以把这个类的实例当作这些interface中的任何一个来用。在生成动态代理类的实例时必须提供一个handler,由它接管实际的工作。
动态代理步骤:
- 创建一个实现接口InvocationHandler的类,它必须实现invoke方法
- 创建被代理的类以及接口
- 通过Proxy的静态方法newProxyInstance创建一个代理
- 通过代理调用方法
CGLIB动态代理
CGLIB(Code Generation Library)是一个高性能开源的代码生成包,采用非常底层的字节码技术,对指定的目标类生成一个子类,并对子类进行增强,和JDK动态代理相比,它可以代理没有实现接口的类
下面的代码demo引用了UP主"子烁爱学习"的视频——Java面试必知必会.Java基础.05.动态代理(JDK/CGLIB)中的例子
静态代理
interface Speaker {
void speak();
}
class Lawyer implements Speaker {
ZhangSan zhangSan = new ZhangSan();
@Override
public void speak() {
System.out.println("引用法律条文~~~");
zhangSan.speak();
System.out.println("打人是不对的!");
}
}
class ZhangSan implements Speaker {
@Override
public void speak() {
System.out.println("我老婆打我!");
}
}
public class Test1 {
public static void main(String[] args) {
ZhangSan zhangSan = new ZhangSan();
zhangSan.speak();
Lawyer lawyer = new Lawyer();
lawyer.speak();
}
}
JDK动态代理
public class Test1 {
public static void main(String[] args) {
ZhangSan zhangSan = new ZhangSan();
LawyerProxy lawyerProxy = new LawyerProxy(zhangSan);
Speaker sp = (Speaker) Proxy.newProxyInstance(Test1.class.getClassLoader(), new Class[]{Speaker.class}, lawyerProxy);
sp.speak();
}
}
class Lawyer implements Speaker {
ZhangSan zhangSan = new ZhangSan();
@Override
public void speak() {
System.out.println("引用法律条文~~~");
zhangSan.speak();
System.out.println("打人是不对的!");
}
}
class ZhangSan implements Speaker {
@Override
public void speak() {
System.out.println("我老婆打我!");
}
}
interface Speaker {
void speak();
}
class LawyerProxy implements InvocationHandler {
private Object obj;
public LawyerProxy(Object obj){
this.obj=obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,
String name = method.getName();//得到被代理得方法名
if (name.equals("speak")) {
System.out.println("引用法律条文~~~");
method.invoke(obj, args);
System.out.println("打人是不对的!");
}
return null;
}
}
CGLIB动态代理
public class Test1 {
public static void main(String[] args) {
LawyerInterceptor lawyerInterceptor = new LawyerInterceptor(new LiSi());
LiSi liSi = (LiSi) Enhancer.create(LiSi.class, lawyerInterceptor);
liSi.speak();
}
}
class LiSi{
public void speak(){
}
}
//CGLIB动态代理
class LawyerInterceptor implements MethodInterceptor {
private Object obj;
public LawyerInterceptor(Object obj){
this.obj=obj;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
String name = method.getName();
if(name.equals("speak")){
System.out.println("引用法律条文~~~");
method.invoke(obj, args);
System.out.println("打人是不对的!");
}
return null;
}
}