什么是AOP?
在运行时,动态的将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。AOP即面向切面编程。使用切面编程,可以将一些系统性的代码提取出来,独立实现,与核心业务代码剥离,比如权限管理、事务管理、日志记录等等。AOP是spring提供的关键特性之一。
AOP的实现原理
AOP分为静态AOP和动态AOP,静态AOP是由AspectJ实现的AOP,动态AOP是指将切面代码进行动态织入实现的AOP,Spring的AOP为动态AOP。实现的技术为:JDK提供的动态代理技术和CGLIB(动态字节码增强技术)两种。尽管实现技术不一样,但 都是基于代理模式 , 都是生成一个代理对象 。
JDK动态代理实现:查看我前面的博文-动态代理,我们看到该方式有一个要求, 被代理的对象必须实现接口,而且只有接口中的方法才能被代理 。也就是jdk代理方式是基于接口的一种代理方式。
CGLIB:字节码生成技术实现AOP,其实就是继承被代理对象,然后Override需要被代理的方法,在覆盖该方法时,自然是可以插入我们自己的代码的。
因为需要Override被代理对象的方法,所以自然CGLIB技术实现AOP时,就 必须要求需要被代理的方法不能是final方法,因为final方法不能被子类覆盖 。
我们使用CGLIB实现上面的例子:
package net.aazj.aop; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CGProxy implements MethodInterceptor{ private Object target; // 被代理对象 public CGProxy(Object target){ this.target = target; } public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable { System.out.println("do sth before...."); Object result = proxy.invokeSuper(arg0, arg2); System.out.println("do sth after...."); return result; } public Object getProxyObject() { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); // 设置父类 // 设置回调 enhancer.setCallback(this); // 在调用父类方法时,回调 this.intercept() // 创建代理对象 return enhancer.create(); } }
public class CGProxyTest { public static void main(String[] args){ Object proxyedObject = new UserServiceImpl(); // 被代理的对象 CGProxy cgProxy = new CGProxy(proxyedObject); UserService proxyObject = (UserService) cgProxy.getProxyObject(); proxyObject.getUser(1); proxyObject.addUser(new User()); } }
观察spring中AOP相关源码可知,如果被代理对象实现了接口,那么就使用JDK的动态代理技术,反之则使用CGLIB来实现AOP,所以 Spring默认是使用JDK的动态代理技术实现AOP的 。
AOP在spring中的使用
Spring中AOP的配置一般有两种方法,一种是使用 <aop:config> 标签在xml中进行配置,一种是使用注解以及@Aspect风格的配置。
1) 基于<aop:config>的AOP配置
<tx:advice id="transactionAdvice" transaction-manager="transactionManager"?> <tx:attributes > <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="append*" propagation="REQUIRED" /> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="get*" propagation="SUPPORTS" /> <tx:method name="find*" propagation="SUPPORTS" /> <tx:method name="load*" propagation="SUPPORTS" /> <tx:method name="search*" propagation="SUPPORTS" /> <tx:method name="*" propagation="SUPPORTS" /> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="transactionPointcut" expression="execution(* net.aazj.service..*Impl.*(..))" /> <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" /> </aop:config>
<bean id="aspectBean" class="net.aazj.aop.DataSourceInterceptor"/> <aop:config> <aop:aspect id="dataSourceAspect" ref="aspectBean"> <aop:pointcut id="dataSourcePoint" expression="execution(public * net.aazj.service..*.getUser(..))" /> <aop:pointcut expression="" id=""/> <aop:before method="before" pointcut-ref="dataSourcePoint"/> <aop:after method=""/> <aop:around method=""/> </aop:aspect> <aop:aspect></aop:aspect> </aop:config>
<aop:aspect> 配置一个切面;
<aop:pointcut>配置一个切点,基于切点表达式;
<aop:before>,<aop:after>,<aop:around>是定义不同类型的advise. a
spectBean 是切面的处理bean
2) 基于注解和@Aspect风格的AOP配置
原文地址:https://www.cnblogs.com/jxxblogs/p/12142734.html
- Windows系统性能分析
- 在Android中调用WebService
- SQL:数据与运算的融合体
- Windows Server AppFabric Caching支持大数据量的配置
- Python函数之匿名函数
- 配置Windows 2008 R2 防火墙允许远程访问SQL Server 2008 R2
- ASP.NET BBcode
- JavaScript 常用算法
- SVG 使用
- 小程能走网店模式?如何做分销模式的小程序?
- IIS 6 下配置以 FastCGI 跑 PHP
- IIS 7.x Application Request Routing(ARR) 502错误的解决方法
- 移动前端头部标签(HTML5 meta)
- 这个行业在汽车圈最落后,正在被物联网和AI改变
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- dubbo本地直连调试注意点
- Tomcat的使用及服务器的一些基础知识
- fastJson 之JSONObject.toJavaObject()方法不能解析嵌套自定义list对象
- 文件包含漏洞学习总结(结尾有实例)
- 树莓派基础实验17:温度传感器实验
- Java Servlet详解(体系结构+注解配置+生命周期)
- RabbitMq如何确保消息不丢失
- 《sql必知必会》——读书笔记(4)
- AkShare-债券数据-国债期货可交割券相关指标
- Linux From Scratch
- 介绍一款 API 敏捷开发工具
- java线程池(五):ForkJoinPool源码分析之一(外部提交及worker执行过程)
- JavaScript中的匿名函数、闭包和BOM
- 【Vue.js】Vue.js中的事件处理、过滤器、过渡和动画、组件的生命周期及组件之间的通信
- 树莓派基础实验18:声音传感器实验