小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
aop基本概念
AOP - Aspect Oriented Programming, 面向切面编程. 通过预编译方式和运行时动态代理的方式实现功能的一种技术.
pointcut - 切入点, 指被增强的方法
advice - 增强或者通知, 给切入点增加功能的方法
aspect - 切面, pointcut + advice, 也就是切点 + 增强称为切面
weaving - 织入, 将切点和增强结合的过程称为织入
常见的增强类型
before - 前置增强, 在指定方法执行之前的增强
after-returning - 后置增强, 在指定方法执行之后的增强
around - 环绕增强, 在指定方法前后都执行的增强
throwing - 异常抛出增强, 在指定方法执行中有异常时的增强
after - 最张执行的方法, 不论指定方法是否有异常抛出
导入aop坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.17.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
创建接口类
public interface TargetInterface {
public void save();
}
创建实现类
public class Target implements TargetInterface {
public void do() {
System.out.println("do...");
}
}
基于xml的aop
创建增强类
public class MyAspect {
public void before() {
System.out.println("前置增强...");
}
public void afterReturning() {
System.out.println("后置增强...");
}
public void throwing() {
System.out.println("异常抛出增强...");
}
public void after() {
System.out.println("最后增强...");
}
}
配置xml
<!-- 目标对象 -->
<bean id="target" class="com.raylee.aop.Target"></bean>
<!-- 切面对象 -->
<bean id="myAspect" class="com.raylee.aop.MyAspect"></bean>
<!-- 配置织入 -->
<aop:config>
<aop:aspect ref="myAspect">
<!-- 表达式抽取 -->
<aop:pointcut id="myPoint" expression="execution(* com.raylee.aop.*.*(..))"/>
<!-- 前置增强 -->
<aop:before method="before" pointcut="execution(* com.raylee.aop.*.*(..))"/>
<!-- 后置增强 -->
<aop:after-returning method="afterReturning" pointcut="execution(* com.raylee.aop.*.*(..))"/>
<!-- 环绕增强 -->
<aop:around method="around" pointcut-ref="myPoint"/>
<!-- 当有异常时进行增强 -->
<aop:after-throwing method="throwing" pointcut-ref="myPoint"/>
<!-- 最终增强 -->
<aop:after method="after" pointcut-ref="myPoint"/>
</aop:aspect>
</aop:config>
进行测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestAop {
@Autowired
private TargetInterface target;
@Test
public void test() {
target.do();
}
}
输出结果
前置增强...
do...
后置增强...
最终增强...
基于注解的aop
定义增强类
@Component("myAspect")
@Aspect
public class MyAspect {
// 定义切点表达式
@Pointcut("execution(* com.raylee.anno.*.*(..))")
public void pointcut() {}
@Before("execution(* com.raylee.anno.*.*(..))")
public void before() {
System.out.println("anno-前置增强...");
}
@AfterReturning("execution(* com.raylee.anno.*.*(..))")
public void afterReturning() {
System.out.println("anno-后置增强...");
}
// @Around("execution(* com.raylee.anno.*.*(..))")
// @Around("pointcut()")
// @Around("MyAspect.pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("anno-环绕前增强...");
Object o = pjp.proceed();
System.out.println("anno-环绕后增强...");
return 0;
}
@AfterThrowing("MyAspect.pointcut()")
public void throwing() {
System.out.println("anno-异常抛出增强...");
}
@After("MyAspect.pointcut()")
public void after() {
System.out.println("anno-最终增强...");
}
}
配置xml
<!-- 组件扫描 --><context:component-scan base-package="com.raylee.anno"/><!-- aop自动代理 --><aop:aspectj-autoproxy/>
进行测试
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:applicationContext-anno.xml")public class TestAop { @Autowired private TargetInterface target; @Test public void test() { target.do(); }}
测试结果
anno-前置增强...do...anno-后置增强...anno-最终增强...