一、AOP概述
AOP(面向切面编程)采用了横向抽取(代理)机制,取代了传统纵向继承体系的重复性代码。
二、AOP术语
1.Joinpoint(连接点):指可以被拦截到的点,在spring中通常指方法。
2.pointcut:指被拦截的点。
3.Advice:指拦截之后的动作。
4.Target:被增强的对象。
5.Weaving:指创建代理对象的过程。
6.Aspect:pointcut和Advice的组合。
三、JDK动态代理
1.创建测试接口和类。
UserDao
public interface UserDao { public void save(); public void update(); public void delete(); public void find(); }
UserDaoImp
public class UserDaoImpl implements UserDao { public void save() { System.out.println("保存用户。。。"); } public void update() { System.out.println("更新用户。。。"); } public void delete() { System.out.println("删除用户。。。"); } public void find() { System.out.println("查找用户。。。"); } }
自定义代理类MyJdkProxy
public class MyJdkProxy implements InvocationHandler{ private UserDao userDao; public MyJdkProxy(UserDao userDao){ this.userDao = userDao; } public Object createProxy(){ Object proxy = Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(),this);//被增强的类的接口的类加载器,接口的信息,InvocationHandler实例 return proxy; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //增强方法 if ("save".equals(method.getName())){ System.out.println("权限校验"); return method.invoke(userDao,args); } return method.invoke(userDao,args); } }
4.测试类:
@Test public void demo1(){ UserDao dao = new UserDaoImpl(); UserDao proxy = (UserDao) new MyJdkProxy(dao).createProxy(); proxy.save(); proxy.delete(); proxy.find(); proxy.update(); }
四、Cglib实现代理
1、为什么要使用cglib?
对于那些没有实现接口的业务类,无法使用jdk动态代理,可以使用cglib,他会为你的类创建一个子类。
2、创建Demo类ProductDao
public class ProductDao { public void update(){ System.out.println("修改商品"); } public void delete(){ System.out.println("删除商品"); } public void find(){ System.out.println("查找商品"); } public void add(){ System.out.println("增加商品"); } }
3.代理类
public class MyCjlib implements MethodInterceptor{ private ProductDao dao; public MyCjlib(ProductDao dao){ this.dao = dao; } public Object createProxy(){ //创建核心对象 Enhancer enhancer= new Enhancer(); //设置父类 enhancer.setSuperclass(dao.getClass()); //设置回调 enhancer.setCallback(this); //产生代理对象 Object proxy = enhancer.create(); return proxy; } public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { if ("add".equals(method.getName())){ System.out.println("代理方法执行了....."); return methodProxy.invokeSuper(o,objects); } return methodProxy.invokeSuper(o,objects); } }
4.测试
@Test public void demo1() { ProductDao dao = new ProductDao(); ProductDao proxy = (ProductDao) new MyCjlib(dao).createProxy(); proxy.add(); proxy.find(); proxy.delete(); proxy.update(); } }
五、总结
1.spring在运行期间动态的生成动态代理对象,不需要特殊的编译器。
2.spring aop底层是通过jdk动态代理和cglib进行织入。
3.若目标对象实现了接口,spring会使用java.lang.reflect.Proxy类代理。
4.若目标对象没有实现接口,spring会使用cglib生成目标对象的子类。
5.程序应该优先为实现了接口的类创建代理,便于程序解耦维护。