一.AOP简介
Aop------面向切面编程(Aspect Oriented Programing)在传统的编程实践中,对于系统中有些行为,我们无法分装在单个的模块中,而且这些功能与行为通常并不实现系统的业务功能,但辅助系统业务功能的实现,并散布在实现系统业务功能的多个模块中.如果采用传统的OOP编程,通常会造成这些功能的代码纠缠于实际的业务代码,造成代码纠结,同时带来了代码的侵入性.
为此,我们希望能够将这些无法分装在单个模块中的功能与行为,集中于一个横切面(Cross-cutting)上,然后在这个横切面上进行代码的编写,编写完成之后通过织入(Weaving)机制,将这个横切面织入到系统的业务功能模块中,使得业务功能的实现都需要通过改横切面,从而实现在实际的业务功能之前或者之后也同时实现了该横切面所提供的功能和行为.
程序运行流程如下:
二.Aop常用概念
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/46e887ec5a2b7b0ea24690746717071f.png)
2.1 Advice(增强/通知)
所需要的横切面的功能m,比如日志,事务处理等
2.2 PointCut(切点)
程序运行中的某个阶段点,如某个方法调用全,后,异常抛出等.在这个阶段点处,
Advice所定义的功能和行为被织入到实际的业务功能中.
2.3 JoinPoint(连接点)
指具体的某个类的某个方法的切点位置.比UserInfo类的getUserName()方法执行前,后等
2.4 Introduction(引阶))
是一种比较特殊的增强类型,它不是目标方法周围织入增强,而是为目标创建新的方法和属性.
所以引阶增强的连接点是类级别的.
2.5 target(目标对象)
只将被加入横切代码Advice的执行对象
2.6 织入(Weaving)
将Advice加入到目标对象的指定连接点的过程.
织入分为3种类型:
编译期织入:指在代码编写时织入的代码;
类加载期织入:指在类加载器加载时织入;
运行期织入:在程序运行时动态加入的代码(动态代理)
2.7 代理(Proxy)
(1).JDK动态代理
Jdk1.3以后,java提供了动态代理技术,允许开发者在运行期创建接口的代理实例
(2)Cglib动态代理
在运行时动态生成一个子类对象,在子类对象中拦截父类所有方法的调用
2.8 切面(Aspect)
切面包含横切代码和连接点信息,所以一个切点无法构成一个切面,必须有切点+增强,或者是一个增强构成一个切面.
把一个功能增强织入到一个切点上就形成了切面
三.Spring-AOP示例 配置文件写法:
3.1 构建不带模板的maven-java工程
发现复写方法时报红,这是因为jdk编译版本过低(jdk1.5),在pom.xml中添加jdk插件<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
3.2 配置文件
spring-config.xml3.3 测试类
运行结果:
配置文件有两种写法:
(1)
<bean id="myAdvice1" class="com.whx.service.advices.MyAdvice1"></bean>
<bean id="myAdvice2" class="com.whx.service.advices.MyAdvice2"></bean>
<bean id="myAdvice3" class="com.whx.service.advices.MyAdvice3"></bean>
<!--aop核心配置-->
<aop:config>
<!--指明切点位置-->
<aop:pointcut id="myPointCut1" expression="bean(userServiceImpl)"></aop:pointcut>
<aop:pointcut id="myPointCut2" expression="bean(orderServiceImpl)"></aop:pointcut>
<!--将增强织入切点形成切面-->
<aop:advisor advice-ref="myAdvice1" pointcut-ref="myPointCut1"></aop:advisor>
<aop:advisor advice-ref="myAdvice2" pointcut-ref="myPointCut1"></aop:advisor>
<aop:advisor advice-ref="myAdvice3" pointcut-ref="myPointCut1"></aop:advisor>
</aop:config>
(2)
<bean id="beforeAdvice" class="com.whx.service.advice2.BeforeAdvice"></bean>
<!--aop核心配置-->
<aop:config>
<aop:pointcut id="myPC1" expression="bean(userServiceImpl)"/>
<aop:aspect ref="beforeAdvice">
<aop:before method="dosomethingBefore" pointcut-ref="myPC1"></aop:before>
</aop:aspect>
</aop:config>
四.AOP的五种功能增强
按照位置划分:4.1 前置切面:before
<!--aop核心配置-->
<aop:config>
<aop:pointcut id="myPC1" expression="bean(userServiceImpl)"/>
<aop:aspect ref="beforeAdvice">
<aop:before method="dosomethingBefore" pointcut-ref="myPC1"></aop:before>
</aop:aspect>
</aop:config>
4.2 后置切面:after
<!--aop核心配置-->
<aop:config>
<aop:pointcut id="myPC1" expression="bean(userServiceImpl)"/>
<aop:aspect ref="afterAdvice">
<aop:after method="doSomethingAfter" pointcut-ref="myPC1"></aop:after>
</aop:aspect>
</aop:config>
4.3 报错时执行:after-throwing
<!--aop核心配置-->
<aop:config>
<aop:pointcut id="myPC1" expression="bean(userServiceImpl)"/>
<aop:aspect ref="exceptionAdvice">
<aop:after-throwing method="onError" pointcut-ref="myPC1"></aop:after-throwing>
</aop:aspect>
</aop:config>
4.4 不报错执行:after-returning
<!--aop核心配置-->
<aop:config>
<aop:pointcut id="myPC1" expression="bean(userServiceImpl)"/>
<aop:aspect ref="noException">
<aop:after-returning method="notError" pointcut-ref="myPC1"></aop:after-returning>
</aop:aspect>
</aop:config>
4.5 环绕切面:around
<!--aop核心配置-->
<aop:config>
<aop:pointcut id="myPC1" expression="bean(userServiceImpl)"/>
<aop:aspect ref="aroundAdvice">
<aop:around method="beforeAndAfter" pointcut-ref="myPC1"></aop:around>
</aop:aspect>
</aop:config>
五.基于注解操作AOP
配置文件添加AOP对于注解的支持:<!--AOP对于注解的支持-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
描述切点位置@Pointcut
@Component
public class MyPointCut {
@Pointcut("bean(userServiceImpl)")
public void pc1(){
}
}
5.1 前置切点:
@Aspect @Before@Component
@Aspect
public class BeforeAdvice {
@Before("com.whx.service.advice2.MyPointCut.pc1()")
public void dosomethingBefore(){
System.out.println("BeforeAdvice.dosomethingBefore");
}
}
5.2 后置切点:
@Aspect @After@Component
@Aspect
public class AfterAdvice {
@After("com.whx.service.advice2.MyPointCut.pc1()")
public void doSomethingAfter(){
System.out.println("AfterAdvice.doSomethingAfter");
}
}
5.3 不报错切点::
@Apsect @AfterReturning@Component
@Aspect
public class NoException {
@AfterReturning("com.whx.service.advice2.MyPointCut.pc1()")
public void notError(){
System.out.println("NoException.notError");
}
}
5.4 报错执行切点:::
@Apsect @AfterThrowing@Component
@Aspect
public class ExceptionAdvice {
@AfterThrowing("com.whx.service.advice2.MyPointCut.pc1()")
public void onError(){
System.out.println("ExceptionAdvice.onError");
}
}
5.5 环绕切点:::
@Apsect @Around@Component
@Aspect
public class AroundAdvice {
@Around("com.whx.service.advice2.MyPointCut.pc1()")
public void beforeAndAfter(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("AroundAdvice.before.");
//调用执行原始功能
proceedingJoinPoint.proceed();
System.out.println("AroundAdvice.after");
}
}
风里雨里,我在善知教育等你!!
需要加Q:1763481971