AOP的底层采用了代理技术,代理技术提供了两种,一种是JDK动态代理,另一种是CGLIB动态代理。
基于JDK的动态代理:必须是面向接口,只有实现了具体的接口的类才能生成代理对象。
基于CGLIB的动态代理:对于没有实现了接口的类,也可以生成代理,生成这个类的子类方式。
一般如果实现接口,使用JDK动态代理完成AOP。没有实现接口,使用CGLIB动态代理实现AOP。
JDK动态代理的实现
UserDao,UserDaoImpl:
package com.spring.demo06; public interface UserDao { public void save(); public void update(); }
package com.spring.demo06; public class UserDaoImpl implements UserDao{ @Override public void save() { System.out.println("保存数据库。。。"); } @Override public void update() { System.out.println("更新数据库。。。"); } }
JDK动态代理的工具类:
package com.spring.demo06; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /* * 使用JDK的方式生成代理对象 */ public class MyProxyUtils { public static UserDao getProxy( UserDao userDao) { //使用Proxy类型生成一个代理对象 UserDao proxy = (UserDao)Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), new InvocationHandler() { //代理对象的方法一执行,invoke中的方法就执行一次 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //如果save方法添加记录日志功能 if("save".equals(method.getName())) { System.out.println("记录日志。。。。"); } System.out.println("代理对象。。。。"); //让UserDaoImpl中的save或者update方法正常执行 return method.invoke(userDao, args); } }); //返回代理对象 return proxy; } }
测试:
package com.spring.demo06; import org.junit.Test; public class TestAOP { @Test public void run() { //目标对象 UserDao userDao = new UserDaoImpl(); userDao.save(); userDao.update(); System.out.println("================================"); //使用工具类获取代理对象 UserDao proxy = MyProxyUtils.getProxy(userDao); //调用代理对象的方法 proxy.save(); proxy.update(); } }
运行结果:
CGLIB动态代理的实现
UserDaoImpl:
package com.spring.demo07; public class UserDaoImpl{ public void save() { System.out.println("保存数据库。。。"); } public void update() { System.out.println("更新数据库。。。"); } }
动态代理工具类:
package com.spring.demo07; import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; /* * 使用CGLIB的方式生成代理对象 */ public class MyCglibUtils { public static UserDaoImpl getProxy() { Enhancer enhancer = new Enhancer(); //设置父类 enhancer.setSuperclass(UserDaoImpl.class); //设置回调函数 enhancer.setCallback(new MethodInterceptor() { //代理对象的方法执行,回调函数就会执行 @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("CGLIB代理对象"); if("save".equals(method.getName())) { System.err.println("记录日志。。。。"); } //正常执行 return methodProxy.invokeSuper(obj, args); } }); //生成代理对象 UserDaoImpl proxy = (UserDaoImpl)enhancer.create(); return proxy; } }
测试:
package com.spring.demo07; import org.junit.Test; public class TestAOP { @Test public void run() { //目标对象 UserDaoImpl userDao = new UserDaoImpl(); userDao.save(); userDao.update(); System.out.println("================================"); //使用CGLIB的方式生成代理对象 UserDaoImpl proxy = MyCglibUtils.getProxy(); //调用代理对象的方法 proxy.save(); proxy.update(); } }
运行结果: