AOP概述
在软件行业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码。
AOP的实现原理
aop底层将采用代理机制进行实现。
实现方式
- spring采用 jdk 的动态代理Proxy:要提供接口和实现类。
- spring 采用 cglib字节码增强:提供实现类即可(不一定要提供接口,更加常用)。
AOP相关术语
名称 | 含义 |
---|---|
target | 目标类,需要被代理的类。 |
Joinpoint | 连接点,指那些可能被拦截到的方法。 |
PointCut | 切入点,即已经被增强的连接点。 |
advice | 通知/增强,增强代码。 |
Weaving | 织入,指把增强advice应用到目标对象target来创建新的代理对象proxy的过程 |
proxy | 代理类,一般将目标类和切面类结合并强转为Proxy类型,即代理类 |
Aspect | 切面类,切入点和通知的结合 |
实例1:jdk的动态代理
第一步,提供目标类及其接口。
第二步,写切面类
第三步,编写工厂类,用于生产代理类。
第四步,测试。
@Test
public void testAOP(){
IUserService ius = MyBeanFactory.createUserService();
ius.addUser();
.....
}
小结:AOP编程的作用
- 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
- AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码。
- 经典应用:事务管理、性能监视、安全检查、缓存 、日志等。
实例2:cglib增强代码
-
原理:采用字节码增强框架 cglib,在运行时创建目标类的子类,从而对目标类进行增强。即目标类和代理类是代理关系。
-
相关jar包:
核心:hibernate-distribution-3.6.10.Final\lib\bytecode\cglib\cglib-2.2.jar
依赖:struts-2.3.15.3\apps\struts2-blank\WEB-INF\lib\asm-3.3.jar
注意:spring-core.xxxx.jar 已经整合以上两个内容。 -
代码实现:第一步,第二步代码同实例1
第三步,编写工厂类。
Enhancer类:增强类,cglib的核心类。
AOP通知类型
Spring按照通知Advice在目标类方法的连接点位置,可以分为5类。
类型名 | 含义 |
---|---|
前置通知 | org.springframework.aop.MethodBeforeAdvice,在目标方法执行前实施增强 |
后置通知 | org.springframework.aop.AfterReturningAdvice,在目标方法执行后实施增强 |
环绕通知 | org.aopalliance.intercept.MethodInterceptor,在目标方法执行前后实施增强 |
异常抛出通知 | org.springframework.aop.ThrowsAdvice,在方法抛出异常后实施增强 |
引介通知 | org.springframework.aop.IntroductionInterceptor,在目标类中添加一些新的方法和属性 |
Spring AOP全自动编程
目标:理解什么是全自动织入。
第一步,导入jar包。
com.springsource.org.aspectj.weaver-xxxx.RELEASE.jar
第二步,配置文件中配置AOP命名空间
第三步,配置文件配置目标类和切面类的bean。
<!-- 目标类 -->
<bean id="userService" class="..."/ >
<!-- 切面类 -->
<bean id="myAspect" class="..."/>
第四步,AOP配置
<aop:config proxy-target-class="true">
<aop:pointcut expression="execution( ....... )" id="myPointCut" />
<aop:advisor advise-ref="myAspect" pointcut-ref="myPointCut" />
</aop:config>
第四步说明
proxy-target-class=“true”:true指使用cglib代理。
切入点表达式:见下文。
AspectJ入门
AspectJ是一个基于Java语言的AOP框架,在Spring2.0后新增了对AspectJ切入点表达式的支持。
1.切入点表达式:
语法:execution(修饰符 返回值 包.类.方法名(参数) throws异常)
名称 | 说明 |
---|---|
修饰符 | * 表示任意,可以省略 |
返回值 | *表示任意,不可省略 |
包名 | com… 表示com下所有子包,*表示任意,可以省略 |
类名 | User* 表示以User开头,结尾同理,* 表示任意,可以省略 |
方法名 | 开头结尾的用法同上,*表示任意,可以省略 |
参数 | ()表示无参,(. .)表示任意参数 |
throws | 一般省略 |
2.AspectJ通知类型
名称 | 含义 |
---|---|
before | 前置通知,在方法执行前执行,常用于各种校验 |
afterReturning | 后置通知,方法正常返回后执行,常用于常规数据处理 |
around | 环绕通知,方法执行前后分别执行 |
afterThrowing | 抛出异常通知,方法抛出异常后执行 |
after | 最终通知,方法执行完毕后执行,无论是否有异常 |
实例1:基于xml
第一步,导包
com.springsource.org.aopalliance-xxxx.jar |
---|
spring-aop-xxxx.jar |
spring-aspects-xxxx.jar |
com.springsource.org.aspectj.weaver-xxxx.jar |
第二步,实现类和切面类
第三步,xml配置文件
1.配置AOP命名空间
2.配置目标类和切面类的bean
3.aop配置
实例2:基于注解
第一步,声明使用注解
第二步,注解代替bean的配置
第三步,声明切面
第四步,声明通知(以前置通知为例)
第五步,声明公共切入点
测试代码略