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实现

相关内容

热门资讯

常用商务英语口语   商务英语是以适应职场生活的语言要求为目的,内容涉及到商务活动的方方面面。下面是小编收集的常用商务...
六年级上册英语第一单元练习题   一、根据要求写单词。  1.dry(反义词)__________________  2.writ...
复活节英文怎么说 复活节英文怎么说?复活节的英语翻译是什么?复活节:Easter;"Easter,anniversar...
2008年北京奥运会主题曲 2008年北京奥运会(第29届夏季奥林匹克运动会),2008年8月8日到2008年8月24日在中华人...
英语道歉信 英语道歉信15篇  在日常生活中,道歉信的使用频率越来越高,通过道歉信,我们可以更好地解释事情发生的...
六年级英语专题训练(连词成句... 六年级英语专题训练(连词成句30题)  1. have,playhouse,many,I,toy,i...
上班迟到情况说明英语   每个人都或多或少的迟到过那么几次,因为各种原因,可能生病,可能因为交通堵车,可能是因为天气冷,有...
小学英语教学论文 小学英语教学论文范文  引导语:英语教育一直都是每个家长所器重的,那么有关小学英语教学论文要怎么写呢...
英语口语学习必看的方法技巧 英语口语学习必看的方法技巧如何才能说流利的英语? 说外语时,我们主要应做到四件事:理解、回答、提问、...
四级英语作文选:Birth ... 四级英语作文范文选:Birth controlSince the Chinese Governmen...
金融专业英语面试自我介绍 金融专业英语面试自我介绍3篇  金融专业的学生面试时,面试官要求用英语做自我介绍该怎么说。下面是小编...
我的李老师走了四年级英语日记... 我的李老师走了四年级英语日记带翻译  我上了五个学期的小学却换了六任老师,李老师是带我们班最长的语文...
小学三年级英语日记带翻译捡玉... 小学三年级英语日记带翻译捡玉米  今天,我和妈妈去外婆家,外婆家有刚剥的`玉米棒上带有玉米籽,好大的...
七年级英语优秀教学设计 七年级英语优秀教学设计  作为一位兢兢业业的人民教师,常常要写一份优秀的教学设计,教学设计是把教学原...
我的英语老师作文 我的英语老师作文(通用21篇)  在日常生活或是工作学习中,大家都有写作文的经历,对作文很是熟悉吧,...
英语老师教学经验总结 英语老师教学经验总结(通用19篇)  总结是指社会团体、企业单位和个人对某一阶段的学习、工作或其完成...
初一英语暑假作业答案 初一英语暑假作业答案  英语练习一(基础训练)第一题1.D2.H3.E4.F5.I6.A7.J8.C...
大学生的英语演讲稿 大学生的英语演讲稿范文(精选10篇)  使用正确的写作思路书写演讲稿会更加事半功倍。在现实社会中,越...
VOA美国之音英语学习网址 VOA美国之音英语学习推荐网址 美国之音网站已经成为语言学习最重要的资源站点,在互联网上还有若干网站...
商务英语期末试卷 Part I Term Translation (20%)Section A: Translate ...