AOP的底层原理:动态代理
使用动态代理时会生成一个动态代理类
动态代理类是在程序运行期间由jvm通过反射等机制动态生成的。
所以不存在代理类的字节码文件(因为没有经历编译阶段),代理对象和真实对象的关系是在程序运行期间才确定的。
JDK动态代理
JDK的代理方式 只能针对接口,目标必须实现接口,同时代理类也实现了和目标对象同样的接口
package ThreadPoolLearn;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxyDemo {
interface Foo{
void foo();
}
static class Target implements Foo{
@Override
public void foo() {
System.out.println("target foo");
}
}
//JDK的代理方式 只能针对接口,目标必须实现接口,同时代理类也实现了和目标对象同样的接口
//目标类可以是final
public static void main(String[] args) {
//目标类对象
Target target=new Target();
ClassLoader loader=JdkProxyDemo.class.getClassLoader();
//动态代理类是在程序运行期间由jvm通过反射等机制动态生成的,
//所以不存在代理类的字节码文件(因为没有经历编译阶段),代理对象和真实对象的关系是在程序运行期间才确定的。
//下面的方法最终会返回实现接口的代理对象
Foo proxy=(Foo) Proxy.newProxyInstance(loader/*类加载器,用来加载运行期间生成的字节码*/, new Class[]{Foo.class}/*要实现的接口*/,
new InvocationHandler()/*用于执行代理类增强的方法*/ {
@Override
public Object invoke(Object proxy/*代理对象自己*/, Method method/*正在执行的方法对象*/, Object[] args/*方法中的实际参数*/) throws Throwable {
System.out.println("before");
//将代理类和要增强的类结合起来
Object result=method.invoke(target,args);
return result;//让代理类放回目标方法执行的结果
}
});
proxy.foo();
}
}
Cglib动态代理
通过Enhancer创建代理对象
创建的代理对象是被代理对象的子类形
因此目标类不能用final修饰
目标方法也不能用final修饰,代理类代理该方法是重写方法
能通过methodProxy,避免反射调用目标,可以提高效率
Object result2=methodProxy.invoke(target,args);
package ThreadPoolLearn;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyDemo {
static class Target{
public void foo(){
System.out.println("target foo");
}
}
public static void main(String[] args) {
Target target=new Target();
//通过Enhancer创建代理对象
//创建的代理对象时被代理对象的子类形
//因此目标类不能用final修饰
//目标方法也不能用final修饰,代理类代理该方法是重写方法
Target proxy=(Target) Enhancer.create(Target.class/*目标类*/, new MethodInterceptor()/*用于执行代理类增强的方法*/ {
@Override
public Object intercept(Object p/*代表代理类自己*/, Method method/*代理类中执行的方法*/, Object[] args/*方法执行时的实际参数*/,
MethodProxy methodProxy) throws Throwable {
System.out.println("before ");
Object result=method.invoke(target,args);//使用方法反射调用目标
//methodProxy,避免反射调用目标
Object result2=methodProxy.invoke(target,args);
//避免反射调用目标,使用代理对象自己
Object result3=methodProxy.invokeSuper(p,args);
System.out.println("after ");
return null;
}
});
proxy.foo();
}
}