什么是动态代理
spring aop面向切面编程,具有拦截功能,在框架编程中有着重要作用,而spirng aop的底层正是通过动态代理完成的。说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常时候执行。不同的切入时机对应不同的Interceptor的种类,如BeforeAdviseInterceptor,AfterAdviseInterceptor以及ThrowsAdviseInterceptor等)。
spring aop底层主要用到了两种动态代理,jdk动态代理和cglib动态代理
jdk和cglib
相同点
都可以进行代理,植入拓展功能
不同点
1.jdk动态代理是由java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的(asm:一个短小精悍的字节码操作框架 它负责生成从被代理类中扫描出的方法的字节码并将这些方法生成字节码暂存在内存中。然后我们通过方法将这些字节码转换成class类型,最后利用反射创建代理类的实例返回)
2.反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效。
3.dk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。
jdk测试代码如下
interface ProxyTest1 {
String getNumber();
}
public class ProxyTest implements ProxyTest1{
public String getNumber(){
String data = "真实类开始了";
return data;
}
}
class ProxyTestProxy implements InvocationHandler{
Object proxyTest;
public ProxyTestProxy(Object proxyTest){
this.proxyTest = proxyTest;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理类先开始");
Object object = method.invoke(proxyTest,args);
System.out.println("代理类结束");
return object;
}
}
class initTest {
public static void main(String[] args) {
ProxyTest1 proxyTest = new ProxyTest();
ProxyTestProxy proxyTestProxy = new ProxyTestProxy(proxyTest);
ProxyTest1 proxyTest1 = (ProxyTest1)Proxy.newProxyInstance(proxyTest.getClass().getClassLoader(),
proxyTest.getClass().getInterfaces(),
proxyTestProxy);
proxyTest1.getNumber();
}
}
结果:
代理类先开始
真实类开始了
代理类结束
cglib动态代理方法
public class CgLibTest {
int getNumber(){
return 4;
}
}
class MyCglibTest implements MethodInterceptor{
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("代理类先执行");
Object object = methodProxy.invokeSuper(o,objects);
System.out.println(object);
return object;
}
}
class initCglibTes{
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(CgLibTest.class);
enhancer.setCallback(new MyCglibTest());
CgLibTest cgLibTest = (CgLibTest)enhancer.create();
cgLibTest.getNumber();
}
}
结果:
代理类先执行
4
总结:运用代理可以实现拦截或者增加新的功能