这几天学spring的源码遇到的,发现自己没用过都,简单学习一下。
介绍:
动态代理是Java编程语言中的一种特性,允许在运行时创建代理类和对象。它主要用于实现AOP(面向切面编程)和在运行时处理其他类的方法调用,例如远程方法调用(RPC)、事务管理等。
在Java中,有两种主要的动态代理实现方式:
-
基于接口的动态代理:使用Java自带的
java.lang.reflect.Proxy
类。基于接口的动态代理要求被代理的类必须实现至少一个接口,代理对象会实现相同的接口,并在运行时处理接口方法的调用。该方式是Java标准库提供的,但仅支持基于接口的代理。 -
基于类的动态代理:使用第三方库,例如CGLIB(Code Generation Library)。这种方式可以代理那些没有实现接口的类,它通过继承被代理类并重写其方法来创建代理对象。相比于基于接口的动态代理,基于类的动态代理更灵活,但在性能上会有一些开销。
我觉得吧,其实就是对方法的抽取和加强而已。
简单创建:
比如一个明星,唱歌前要收钱,跳舞前要准备场地。
bigStar类:
public class BigStar implements Star{
private String name;
public BigStar(String name) {
this.name = name;
}
public String sing(String singName) {
System.out.println(name + "唱了" +singName);
return "success";
}
public void dance() {
System.out.println("跳舞了");
}
}
就是我们正常的普通的类。
Star接口:
public interface Star {
public String sing(String singName);
public void dance();
}
代理必须通过实现接口,告诉代理对象代理那些方法。
代理的实现类:
public class ProxyUtil {
public static Star createProxy(BigStar bigStar) {
// ClassLoader loader, 类加载器,一般都用的当前类的加载器
// Class<?>[] interfaces, 指定生成的代码有那些方法,可以有多个,用数组接收
// InvocationHandler h) 匿名对象,指定代理干什么事
Star startProxy = (Star)Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
new Class[]{Star.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("sing")) {
System.out.println("唱歌前收钱");
} else if (method.getName().equals("dance")) {
System.out.println("跳舞前准备场地");
}
return method.invoke(bigStar,args);
}
});
return startProxy;
}
}
ClassLoader loader, 类加载器,一般都用的当前类的加载器
Class<?>[] interfaces, 指定生成的代码有那些方法,可以有多个,用数组接收
InvocationHandler h) 匿名对象,指定代理干什么事
test:
public class Test {
public static void main(String[] args) {
BigStar lpy = new BigStar("lpy");
Star proxy = ProxyUtil.createProxy(lpy);
String res = proxy.sing("晴天");
proxy.dance();
}
}
运行结果:
原理:
看一下这个调用过程就懂了,不再多说了。