1、静态代理
2、JDK动态代理
JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口,其核心是InvocationHandler接口和Proxy类。
jdk动态代理之所以只能代理接口是因为代理类本身已经extends了Proxy,而java是不允许多重继承的,但是允许实现多个接口,因此才有cglib的需要吧。
public interface Math { public int div(int a, int b) throws Exception; } @Component public class MathCaculator implements Math { public MathCaculator() { System.out.println("MathCaculator构造器***************"); } public int div(int a, int b) throws Exception { System.out.println("除法的方法主体"); return a/b; } } public class DynamicProxy implements InvocationHandler { Object targetObject; public Object getProxyObejct(Object targetObject) { this.targetObject = targetObject; return Proxy.newProxyInstance(targetObject.getClass().getClassLoader() ,targetObject.getClass().getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long startTime = System.currentTimeMillis(); Thread.sleep(100); Object result=method.invoke(targetObject, args); long endTime = System.currentTimeMillis(); System.out.println("耗时"+(endTime-startTime)+"秒"); System.out.println("结果+"+result); return result; } } public class Test { public static void main(String[] args) throws Exception { Math math = (Math) new DynamicProxy().getProxyObejct(new MathCaculator()); math.div(10,5); } }
3、CGLIB动态代理
对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
如果目标类没有实现接口,那就要选择使用CGLIB来动态代理目标类。CGLIB是通过继承的方式做的动态代理,因此,如果某个类被标记为final,那么它是无法使用CGLIB做动态代理。CGLIB会使生成的代理类继承当前的对象,并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。
import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CglibDynamicProxy implements MethodInterceptor { Object targetObject; public Object getProxyObject(Object object){ System.out.println("cglib创建代理"); this.targetObject = object; Enhancer enhancer = new Enhancer(); enhancer.setCallback(this); enhancer.setSuperclass(targetObject.getClass()); return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { long startTime = System.currentTimeMillis(); Thread.sleep(100); Object result=methodProxy.invoke(targetObject, args); long endTime = System.currentTimeMillis(); System.out.println("耗时"+(endTime-startTime)+"秒"); System.out.println("结果+"+result); return result; } }