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

相关内容

热门资讯

我是孙悟空想象作文 我是孙悟空想象作文(通用82篇)  在平凡的学习、工作、生活中,大家都跟作文打过交道吧,作文是一种言...
未来的汽车的作文600字 关于未来的汽车的作文600字(通用22篇)  在我们平凡的日常里,大家都尝试过写作文吧,作文一定要做...
我喜欢的动物二年级作文 我喜欢的动物二年级作文(精选125篇)  在日常生活或是工作学习中,大家最不陌生的就是作文了吧,作文...
生豆芽的观察日记 生豆芽的观察日记(精选20篇)  时间如快马般匆匆,一天又过去了,这一天里,大家身边一定有一些有趣的...
星际之旅 想象作文800字 星际之旅 想象作文800字  无论是在学校还是在社会中,大家都不可避免地要接触到作文吧,作文是一种言...
别样感受小学生作文 别样感受小学生作文  在日常学习、工作抑或是生活中,大家最不陌生的就是作文了吧,作文是从内部言语向外...
短篇童话故事 短篇童话故事【精】短篇童话故事1  有一年冬天非常的冷,而松鼠却躲在它温暖的树洞里津津有味的吃着它秋...
美丽的童话作文 美丽的童话作文15篇  在平平淡淡的学习、工作、生活中,大家都经常接触到作文吧,通过作文可以把我们那...
初中作文读后感 初中作文读后感(集锦15篇)  在学习、工作或生活中,大家都经常接触到作文吧,作文要求篇章结构完整,...
编写一个童话故事作文 编写一个童话故事作文  在生活、工作和学习中,许多人都有过写作文的经历,对作文都不陌生吧,借助作文人...
描写自己的作文 关于描写自己的作文(通用6篇)  无论在学习、工作或是生活中,大家对作文都不陌生吧,作文是从内部言语...
管理自己作文 精选管理自己作文四篇  在平平淡淡的学习、工作、生活中,大家一定都接触过作文吧,作文一定要做到主题集...
我想变成什么作文 我想变成什么作文11篇  在日复一日的学习、工作或生活中,大家都写过作文吧,借助作文可以提高我们的语...
哈利波特读后感作文500字 【热门】哈利波特读后感作文500字3篇  在日常学习、工作和生活中,说到作文,大家肯定都不陌生吧,写...
多肉的观察日记 多肉的观察日记(通用7篇)  一天即将完结,这一天里,有没有哪件事或某个人触动到我们呢?是时候静下心...
植物生长观察日记 植物生长观察日记(精选29篇)  已到了一天的末尾,在你心中有什么感想呢?是时候用心地写一篇日记了。...
胎教小故事 胎教小故事(精选34篇)  故事一般都和原始人类的生产生活有密切关系,他们迫切地希望认识自然,于是便...
未来的汽车的作文 未来的汽车的作文(精选93篇)  在日常学习、工作或生活中,许多人都有过写作文的经历,对作文都不陌生...
写一处自然景观作文400字 写一处自然景观作文400字合集5篇  在日常学习、工作或生活中,说到作文,大家肯定都不陌生吧,作文是...
观察小动物日记 关于观察小动物日记(通用41篇)  一天的时间眼看就要结束了,今天我们都做了什么了呢?让我们一起认真...