Spring Aop 详解
创始人
2024-05-31 11:33:56
0

主要内容:

  • 了解Spring AOP的概念及其术语
  • 熟悉Spring AOP的JDK动态代理
  • 熟悉Spring AOP的CGLib动态代理
  • 掌握基于XML的AOP实现
  • 掌握基于注解的AOP实现

 AOP用官方话来说:

AOP即面向切面编程。和OOP(面向对象编程)不同,AOP主张将程序中相同的业务逻辑进行横向隔离,并将重复的业务逻辑抽取到一个独立的模块中,以达到提高程序可重用性和开发效率的目的
在传统的业务处理代码中,通常都会进行事务处理、日志记录等操作。虽然使用OOP可以通过组合或者继承的方式来达到代码的重用,但如果要实现某个功能(如日志记录),同样的代码仍然会分散到各个方法中。

我在举个例子:

为什么要使用aop?我们做一个后台系统,除了登录,注册功能不用用户验证,其他页面都需要用户验证,写的页面越多,这些代码重复率高,你还得写,这个时候我们把相同的功能给抽离出来,用aop来统一处理.aop是一种思想,(spring aop是一个框架.是aop思想的实现)

现在假如,订单系统中有添加订单信息、更新订单信息和删除订单信息3个方法,这3个方法中都包含事务管理业务代码,订单系统的逻辑如图所示。

由订单系统可知,添加订单信息、修改订单信息、删除订单信息的方法体中都包含事务管理的业务逻辑,这就带来了一定数量的重复代码并使程序的维护成本增加。基于AOP,可以为此类问题提供解决方案,AOP可以将事务管理的业务逻辑从这三个方法体中抽取到一个可重用的模块,进而降低横向业务逻辑之间的耦合,减少重复代码。AOP的使用,使开发人员在编写业务逻辑时可以专心于核心业务,而不用过多地关注其他业务逻辑的实现,不但提高了开发效率,又增强了代码的可维护性。 

除了统⼀的⽤户登录判断之外,AOP 还可以实现:

  • 统⼀⽇志记录
  • 统⼀⽅法执⾏时间统计
  • 统⼀的返回格式设置
  • 统⼀的异常处理
  • 事务的开启和提交等

 
也就是说使⽤ AOP 可以扩充多个对象的某个能⼒,所以 AOP 可以说是 OOP(Object Oriented
Programming,⾯向对象编程)的补充和完善。

AOP术语

AOP并不是一个新的概念,AOP中涉及很多术语,如切面、连接点、切入点、通知/增强处理、目标对象、织入、代理和引介等,下面针对AOP的常用术语进行简单介绍。

 

  • 切面是指关注点形成的类(关注点是指类中重复的代码),通常是指封装的、用于横向插入系统的功能类(如事务管理、日志记录等)。在实际开发中,该类被Spring容器识别为切面,需要在配置文件中通过元素指定。
  • 连接点是程序执行过程中某个特定的节点,例如,某方法调用时或处理异常时。在Spring AOP中,一个连接点通常是一个方法的执行。
  • 当某个连接点满足预先指定的条件时,AOP就能够定位到这个连接点,在连接点处插入切面,该连接点也就变成了切入点
  • 通知/增强处理就是插入的切面程序代码。可以将通知/增强处理理解为切面中的方法,它是切面的具体实现。
  • 将切面代码插入到目标对象上,从而生成代理对象的过程。织入可以在编译时,类加
    载时和运行时完成。在编译时进行织入就是静态代理,而在运行时进行织入则是动态代理。
  • 目标对象是指被插入切面的方法,即包含主业务逻辑的类对象。或者说是被一个或者多个切面所通知的对象。
  • 引介是一种特殊的通知,它为目标对象添加一些属性和方法。这样,即使一个业务类原本没有实现某一个接口,通过AOP的引介功能,也可以动态地为该业务类添加接口的实现逻辑,让业务类成为这个接口的实现类。
  • 将通知应用到目标对象之后,程序动态创建的通知对象,就称为代理。代理类既可能是和原类具有相同接口的类,也可能就是原类的子类,可以采用调用原类相同的方式调用代理类。

一个连接点可以不是切入点,但是一个切入点一定是一个连接点

Spring AOP的实现机制

熟悉JDK动态代理,能够说出JDK动态代理的机制

默认情况下,Spring AOP使用JDK动态代理,JDK动态代理是通过
java.lang.reflect.Proxy类实现的
,可以调用Proxy类的newProxyInstance()方法创建代理对象。JDK动态代理可以实现无侵入式的代码扩展,并且可以在不修改源代码的情况下,增强某些方法。

案例演示Spring中JDK动态代理的实现过程:

实现版本一:

 

 

 

package cn.hdc.demo1.entity;import cn.hdc.demo1.dao.UserDao;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** JDK代理类*/
public class MyProxy implements InvocationHandler {//声明目标类接口private UserDao userDao;//创建代理方法public Object createProxy(UserDao userDao) {this.userDao = userDao;// 1.classLoader - 类加载器ClassLoader classLoader = MyProxy.class.getClassLoader();// 2.classes - 被代理对象实现的所有接口Class[] classes = userDao.getClass().getInterfaces();// 3.使用代理类,进行增强,返回的是代理对象   this - 表示代理类JdkProxy本身。return Proxy.newProxyInstance(classLoader, classes, this);}/** 所有动态代理类的方法调用,都会交由invoke()方法去处理* proxy 被代理的对象* method 将要被执行的方法信息(反射)* args 执行方法时需要的参数*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 创建切面对象MyAspect myAspect = new  MyAspect();// 前增强myAspect.check_permission();// 在目标类上调用方法,并传入参数Object obj = method.invoke(userDao, args);// 后增强myAspect.log();return  obj;}
}

 运行结果:

 

实现版本二:

 

package cn.hdc.component;public class MyAspect {public void check_permission() {System.out.println("模拟检查权限。。。");}public void log() {System.out.println("模拟日志输入,输出");}
}


package cn.hdc.component;import cn.hdc.dao.UserDao;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class MyProxy implements InvocationHandler {private UserDao userDao;public Object createProxy(UserDao userDao) {this.userDao = userDao;//创建jdk的动态代理对象需要三个参数,类加载器,被代理对象实现的接口,处理器(增强功能的具体实现)ClassLoader classLoader = MyProxy.class.getClassLoader();Class[] interfaces = userDao.getClass().getInterfaces();//创建动态代理对象Object proxy = Proxy.newProxyInstance(classLoader, interfaces, this);return proxy;}/*** @param proxy  代理对象本身* @param method 将要增强的方法* @param args   方法的参数* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//创建增强类对象MyAspect myAspect = new MyAspect();myAspect.check_permission();//保证原有功能的执行Object obj = method.invoke(userDao, args);//日志增强myAspect.log();return null;}
}

 

 

CGLib动态代理

JDK动态代理存在缺陷,它只能为接口创建代理对象,当需要为类创建代理对象时,就需要使用CGLib (Code Generation Library)动态代理,CGLib动态代理不要求目标类实现接口,它采用底层的字节码技术,通过继承的方式动态创建代理对象。Spring的核心包已经集成了CGLib所需要的包,所以开发中不需要另外导入JAR包。

实现版本一:

 

 

package cn.hdc.demo2.entity;import cn.hdc.demo1.entity.MyAspect;
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 CglibProxy implements MethodInterceptor {// 代理方法public Object createProxy(Object target) {// 创建一个动态类对象Enhancer enhancer = new Enhancer();// 确定需要增强的类,设置其父类enhancer.setSuperclass(target.getClass());// 添加回调函数enhancer.setCallback(this);// 返回创建的代理类return enhancer.create();}/*** proxy CGlib根据指定父类生成的代理对象* method 拦截的方法* args 拦截方法的参数数组* methodProxy 方法的代理对象,用于执行父类的方法*/public Object intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {// 创建切面类对象MyAspect myAspect = new MyAspect();// 前增强myAspect.check_permission();// 目标方法执行Object obj = methodProxy.invokeSuper(proxy, args);// 后增强myAspect.log();return obj;}
}

 运行结果:

 

实现版本二:

 

 

package cn.hdc.entity;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 MyCglibProxy implements MethodInterceptor {public Object createProxy(Object object) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(object.getClass());enhancer.setCallback(this);return enhancer.create();}/*** 增强功能的具体实现** @param o           代理对象本身* @param method      被代理的方法* @param objects     方法需要的参数* @param methodProxy 代理后的方法* @return* @throws Throwable*/@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {MyAspect myAspect = new MyAspect();myAspect.check_permission();//保证原有功能的执行Object res = methodProxy.invokeSuper(o, objects);myAspect.log();return res;}
}

 

基于xml的Aop实现

基于注解的Aop实现

相关内容

热门资讯

师德师风演讲比赛主持稿 师德师风演讲比赛主持稿范文(通用7篇)  在快速变化和不断变革的今天,很多地方都会使用到主持稿,主持...
结婚仪式主持词 结婚仪式主持词10篇  主持词是各种演出活动和集会中主持人串联节目的串联词。我们眼下的社会,主持人参...
企业年会主持词开场白精选   新年拉近了我们成长的距离,新年染红了我们快乐的生活。下面是CN人才网小编为大家整理的年会主持词开...
教师节座谈会校长致辞 教师节座谈会校长致辞(精选16篇)  在日常学习、工作抑或是生活中,大家对致辞都再熟悉不过了吧,在各...
五一晚会开幕词与闭幕词 五一晚会开幕词与闭幕词  在当今社会生活中,我们经常都会使用到开幕词,开幕词对引导会议或活动顺利进行...
含笑半步颠经典台词 含笑半步颠经典台词  在社会发展不断提速的今天,我们使用上台词的情况与日俱增,台词是构成一个剧本的基...
联谊会主持词 有关联谊会主持词集合8篇  主持词是各种演出活动和集会中主持人串联节目的串联词。在人们积极参与各种活...
晚会闭幕词 晚会闭幕词(通用37篇)  在日新月异的现代社会中,很多情况下我们需要用到主持稿,主持稿起到承上启下...
婚礼主持词 婚礼主持词(精选20篇)  主持词要注意活动对象,针对活动对象写相应的主持词。在人们越来越多的参与各...
半年总结会主持词 半年总结会主持词  以下是由应届毕业生网PQ小编为大家整理出来的半年总结会主持词,仅供参考,半年总结...
最短的对口相声台词 最短的对口相声台词范文  相声是一种中国曲艺表演艺术,源于华北,流行于京津冀,普及于全国及海内外,始...
司仪主持词 精选司仪主持词(精选14篇)  主持词需要富有情感,充满热情,才能有效地吸引到观众。在各种集会、活动...
电影节颁奖典礼主持词 电影节颁奖典礼主持词  颁奖典礼上最重要的就是主持人手中的台词啦!下面来看看小编带来的电影节颁奖典礼...
安全生产会议的致辞 安全生产会议的致辞(精选5篇)  在日常的学习、工作、生活中,要用到致辞的地方还是很多的,致辞具有“...
最新半台词分享 最新三句半台词分享  俺们几个话挺多,大家不要嫌罗嗦,希望能够捧捧场,鼓掌!  北京先把地方占,天津...
《教父》经典台词中英文对照 《教父》经典台词中英文对照  1、To be close to your friend, but c...
播音主持稿 播音主持稿(精选21篇)  在现在的社会生活中,我们很多时候都不得不用到主持稿,主持稿是主持人为把整...
年会主持词 精选年会主持词四篇  主持词要注意活动对象,针对活动对象写相应的主持词。在现今人们越来越重视活动氛围...
金秋国庆主持词开场白 金秋国庆主持词开场白  国庆节是我们祖国母亲的生日,下面unjs小编整理了金秋国庆主持词开场白,欢迎...