(学习笔记仅帮助自己理解记忆,部分内容可能存在理解错误,如有发现,还望指出)
AOP名词解释:
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP主要功能:
- 日志记录
- 性能统计
- 安全控制
- 事务处理
- 异常处理
实现方式:
将其主要功能代码从业务逻辑代码中划分出来,通过对这些行为的分离,将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码,专心于业务的开发,降低程序的耦合度;
AOP相关JAR包:
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>对应版本</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>对应版本</version>
</dependency>
AOP相关术语:
切面(Aspect): 一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的例子。在Spring AOP中,切面可以使用基于模式或者基于@Aspect注解的方式来实现。
连接点(Joinpoint): 在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。在Spring AOP中,一个连接点总是表示一个方法的执行。
通知/增强(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链;
前置增强(before advice),在目标方法执行之前执行;
后置增强:(after[finally] advice),在目标方法执行之后执行(无论是否发生异常);
异常增强(after throwing advice),在目标方法出现异常时执行的代码,可以访问到异常对象,且可以指定出现特定异常执行此方法;
切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上
引入(Introduction): 添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口
目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。
AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
**织入(Weaving): ** 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。
XML方式配置实现AOP:
ApplicationContext.xml:
<bean id="logAdv" class="advice.LoggleAdv"></bean>
<aop:config>
<!--配置切入点-->
<aop:pointcut id="addFun" expression="execution(* service.UserServiceImpl.addUser(..))"/>
<!--配置切面-->
<aop:aspect ref="logAdv">
<aop:before method="before_Adv" pointcut-ref="addFun" />
<aop:after-returning method="after_Adv" pointcut-ref="addFun" returning="result" />
<aop:after-throwing method="throw_Adv" pointcut-ref="addFun" throwing="e"/>
</aop:aspect>
</aop:config>
LoggleAdv .class:
public class LoggleAdv {
public void before_Adv(JoinPoint jp){
User u = (User)jp.getArgs()[0];
System.out.println("-----------------进入前置增强-----------------");
System.out.println("\t操作用户:"+u.getName()+
"\n\t用户类型:"+u.getuType()+
"\n\t传入参数:"+(jp.getArgs().length-1)+
"\n\t执行方法:"+jp.getSignature().toString());
System.out.println("-----------------结束前置增强-----------------");
}
public void after_Adv(JoinPoint jp,Object result){
System.out.println("-----------------进入后置增强-----------------");
System.out.println("\t执行方法:"+jp.getSignature().toString()+
"\n\t返回结果:"+result);
System.out.println("-----------------结束后置增强-----------------");
}
public void throw_Adv(JoinPoint jp,Exception e){
System.out.println("-----------------进入Throw增强-----------------");
System.out.println("\t异常类型:"+e.toString());
System.out.println("-----------------结束Throw增强-----------------");
System.exit(1);
}
}