概述
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP开发是以动态代理为底层原理的,它的开发步骤也与动态代理类似,只是把方法增强部分交给了Spring去管理。
下面介绍AOP开发的两种方式:
- 基于XML的AOP 开发
- 基于注解的AOP 开发
基于XML 的AOP 开发
1. 导入AOP依赖包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!-- AOP -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
2. 创建目标类和接口
public class Target implements TargetInterface {
@Override
public void coreWork() {
System.out.println("===核心业务方法运行===");
}
}
public interface TargetInterface {
public void coreWork();
}
3. 创建切面类(增强方法类)
public class Aspect {
public void before(){
System.out.println("对核心业务方法执行前的增强......");
}
public void after(){
System.out.println("后置增强......");
}
4. 将目标类和切面类交给Spring管理
<!-- 目标对象 -->
<bean id="target" class="com.wang.aop.Target"></bean>
<!-- 切面对象 -->
<bean id="aspect" class="com.wang.aop.Aspect"></bean>
5. 在核心配置文件中配置织入关系
<aop:config>
<aop:aspect ref="aspect">
<aop:before method="before" pointcut="execution(public void com.wang.aop.Target.coreWork())"/>
<aop:after method="after" pointcut="execution(public void com.wang.aop.Target.coreWork())"/>
</aop:aspect>
</aop:config>
测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
@Autowired
private TargetInterface target;
@Test
public void test() {
target.coreWork();
}
}
XML 配置AOP
切点表达式的写法
execution([修饰符] 返回值类型包名.类名.方法名(参数))
- 访问修饰符可以省略
- 返回值类型、包名、类名、方法名可以使用星号*代表任意
- 包名与类名之间一个点. 代表当前包下的类,两个点.. 表示当前包及其子包下的类
- 参数列表可以使用两个点.. 表示任意个数,任意类型的参数列表
通知的配置
<aop:通知类型method=“切面类中方法名” pointcut=“切点表达式"></aop:通知类型>
通知类型 | 标签 | 解释 |
---|---|---|
前置通知 | <aop:before> | 用于配置前置通知。指定增强的方法在切入点方法之前执行 |
后置通知 | <aop:after-returning> | 用于配置后置通知。指定增强的方法在切入点方法之后执行 |
环绕通知 | <aop:around>> | 用于配置环绕通知。指定增强的方法在切入点方法之前和之后都执行 |
异常抛出通知 | <aop:throwing>> | 用于配置异常抛出通知。指定增强的方法在出现异常时执行 |
最终通知 | <aop:after>> | 用于配置最终通知。无论增强方式执行是否有异常都会执行 |
aop织入的配置
<aop:config>
<aop:aspect ref=“切面类”>
<aop:before method=“通知方法名称” pointcut=“切点表达式"></aop:before>
</aop:aspect>
</aop:config>
基于注解的AOP开发
基于注解开发,Spring也提供了注解的AOP开发。
1. 创建目标接口和目标类(内部有切点)
public class Target implements TargetInterface {
@Override
public void coreWork() {
System.out.println("===核心业务方法运行===");
}
}
public interface TargetInterface {
public void coreWork();
}
2. 创建切面类(增强方法类)
public class Aspect {
public void before(){
System.out.println("对核心业务方法执行前的增强......");
}
public void after(){
System.out.println("后置增强......");
}
3. 将目标类和切面类的对象创建权交给spring并使用注解配置织入关系
@Component("aspect")
@Aspect
public class MyAspect {
@Before("execution(* com.wang.aop.innovation.*.*(..))")
public void before(){
System.out.println("对核心业务方法执行前的增强......");
}
@After("execution(* com.wang.aop.innovation.*.*(..))")
public void after(){
System.out.println("后置增强......");
}
}
4. 在配置文件中开启组件扫描和AOP 的自动代理
<context:component-scan base-package="com.wang.aop.innovation"/>
<!--aop的自动代理-->
<aop:aspectj-autoproxy/>
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
@Autowired
private TargetInterface target;
@Test
public void test() {
target.coreWork();
}
}
注解通知的类型
通知类型 | 注解 | 解释 |
---|---|---|
前置通知 | @Before | 用于配置前置通知。指定增强的方法在切入点方法之前执行 |
后置通知 | @after-returning | 用于配置后置通知。指定增强的方法在切入点方法之后执行 |
环绕通知 | @around | 用于配置环绕通知。指定增强的方法在切入点方法之前和之后都执行 |
异常抛出通知 | @throwing | 用于配置异常抛出通知。指定增强的方法在出现异常时执行 |
最终通知 | @after | 用于配置最终通知。无论增强方式执行是否有异常都会执行 |