AOP(Aspect Oriented Programming),即面向切面编程。通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件系统开发中的一个热点,也是spring框架的一个重点。利用AOP可以实现业务逻辑各个部分的隔离,从而使得业务逻辑各个部分的耦合性降低,提高程序的可重用性,同时提高开发效率。
AOP原理:
作用:在程序运行期间,不修改源码对已有方法进行增强,扩展功能。
优势:减少重复代码、提高开发效率、维护方便。
原理: 动态代理技术
说明:在 spring 中,框架会根据目标类是否实现了接口来决定采用哪种动态代理的方式。
如果目标对象实现接口,使用JDK代理。
目标对象没有实现接口使用CGLIB代理。
动态代理:代理类在程序运行时创建的代理方式被成为动态代理。
JDK动态代理有以下特点:
代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们提供目标对象所实现的接口的字节码对象)
动态代理要求目标对象一定要实现接口,所以也叫做接口代理!
回顾JDK动态代理
Proxy类
InvocationHandler接口
动态代理模式的开发步骤
首先需要存在抽象角色,定义所有的功能
真实对象实现抽象角色所有的功能
通过Proxy类,创建代理对象,调用代理方法
在InvocationHandler的invoke对代理的方法有选择的修改或不修改。动态代理模式应用案例:
测试
public class Demo { public static void main(String[] args) throws Exception { /* 最终返回一个代理对象,此代理对象对目标对象的所有方法都进行了代理 最终执行代理对象的任何方法都会执行InvocationHandler中的invoke方法 */ Service o = (Service) Proxy.newProxyInstance( /* 传入目标对象的类加载器 */ ServiceImpl.class.getClassLoader(), /* 传入目标对象的所有实现接口的字节码对象 代理对象就是根据此接口字节码对象来指定代理方法,实现动态方法代理 要不然目标对象增加一个方法,动态代理需要手动添加一个代理方法 */ ServiceImpl.class.getInterfaces(), new InvocationHandler() { @Override //proxy是代理对象 //method是目标对象的方法 //args是目标对象方法的参数 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("增强的代码"); /* 因为method.invoke执行的是目标对象的具体方法,因此必须传入目标对象 */ Object invoke = method.invoke(new ServiceImpl()); System.out.println("增强的代码"); return invoke; } } ); //代理对象执行save方法,最终会执行InvocationHandler中的invoke方法 o.save();
} }
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
小结:JDK提供的动态代理是基于接口的,把目标对象所实现的所有接口的字节码对象传入方法中,JDK能在内存中动态的帮我们创建一个对象,该对象实现的目标对象实现的所有方法。即保证目标对象的所有方法代理对象都能代理到
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
JDK动态代理,要求目标对象一定要实现接口,否则不能用动态代理。
如果目标对象就是没有实现接口,还想对目标对象某个方法进行扩展,怎么办?看CGLIB代理!
代码:
public class Service { public void save(){ System.out.println("保存"); } public void update(){ System.out.println("修改"); } public void delete(){ System.out.println("删除"); } }
public class Demo1 {
@Test public void test1() { //返回一个service的子类 Service serviceProxy = (Service) Enhancer.create(Service.class, new MethodInterceptor() { /* * * proxy:代理对象 * method:要执行的方法对象 * args:要执行的方法的参数 * methodProxy:代理对象的方法对象 * */ @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("增强的代码"); // Object invoke = method.invoke(new Service()); /* methodProxy: 代理对象的方法类,因为cglib代理对目标对象进行继承派生出子类,因此代理对象是目标对象的子类 此代理对象方法类可以执行本代理对象方法,也可以执行 */ Object invoke = methodProxy.invoke(new Service(), args); System.out.println("增强的代码"); return invoke; } });
serviceProxy.save(); }
}
使用CGLIB子类代理:
需要引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,
引入功能包后,就可以在内存中动态构建子类
代理的类不能为final,否则报错
目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
链接:https://pan.baidu.com/s/1q8Gf8V4ILRROqk8tc_qlDQ 提取码:6m9x 代理的实例代码