一、静态代理
1.创建Subject业务接口
/** * 抽象主题:真实业务接口 */ public interface Subject { public void doSomething(); }
2.创建RealSubject实现Subject接口
/** * 真是主题:将业务代码封装到此主题中 */ public class RealSubject implements Subject{ @Override public void doSomething() { System.out.println("真实业务"); } }
3.创建代理类
/* * 代理主题:代理类 生成真实主题对象,调用真是主题的方法 * 程序就不用直接去创建真是主题了,直接调用代理对象 * * * 静态代理:说白了,就是创建一个给程序调用的类(代理类),然后用代理类去调用原始对象 * */ public class ProxySubject implements Subject{ //真实对象 Subject subject=new RealSubject(); @Override public void doSomething() { System.out.println("===========前置增强==========="); subject.doSomething(); System.out.println("===========后置增强==========="); } }
3.创建测试类
public static void main(String[] args) { ProxySubject proxySubject=new ProxySubject(); proxySubject.doSomething();
}
二、JDK动态代理
1.创建业务接口
/**
* 抽象主题:真实业务接口 */ public interface Subject { public void doSomething(); }
2.创建接口实现类
public class RealSubject implements Subject{ @Override public void doSomething() { System.out.println("真实业务"); } }
3.调用管理接口InvocationHandler 创建动态代理类
public static void main(String[] args) { //JDK动态代理:要求必须又抽象主题 //代表的是代理对象 指定对象的原始类型 /* * ClassLoading loader,类加载器:应该是代理对象的类加载器 * Class<?>[] interfaces, 接口:原始对象实现 接口类型 * InvocationHandler h * */ //创建一个原始对象 final Subject subject = new RealSubject(); Subject subjetProxy = (Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("前置增强"); Object invoke = method.invoke(subject, args); System.out.println("后置增强"); return invoke; } }); subjetProxy.doSomething(); }
三、cglib动态代理
1.创建业务类
public class IService { public void doSomething(){ System.out.println("真实业务"); } }
2.创建代理工厂Bean
public static void main(String[] args) { //步骤一:目标对象 final IService iService=new IService(); //步骤二:通过cglib提供的nhancer类 生成代理 Enhancer enhancer=new Enhancer(); //步骤三 :指定需要代理的目标对象模板(将目标对象放入到代理工厂当中,生成代理对象) enhancer.setSuperclass(iService.getClass()); //步骤四:实现增强的处理操作 enhancer.setCallback(new MethodInterceptor() { /** * * @param o 目标对象 * @param method 目标对象的方法 * @param objects 目标对象方法的参数 * @param methodProxy 代理目标对象方法 * @return * @throws Throwable */ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("前置"); Object invoke = methodProxy.invoke(iService, objects); System.out.println("后置"); return invoke; } }); //最后一步 :创建代理 IService iServiceproxy = (IService) enhancer.create(); iServiceproxy.doSomething(); }
四 、总结
JDK动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法;
CGlib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理;
如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
如果目标对象实现了接口,可以强制使用CGLIB实现AOP
[aop:config proxy-target-class="true"] 强制切换成CGLIB动态代理
如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换