AOP的一些名词
连接点:类中可以被增强的方法
切入点:类中实际被增强的方法
通知:实际增强方法的部分
切面:把通知应用到切入点的过程
其中通知常用的有前置通知,后置通知,环绕通知
AOP具体实现
Spring AOP是基于AspectJ实现的,所以需要先引入依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
这里我们通过注解来实现,所以开启注解,然后开启注解扫描的包,同时开启Aseptic生成代理对象
<!-- 开启注解支持-->
<context:annotation-config/>
<!-- 配置要扫描的包下的注解生效-->
<context:component-scan base-package="com.hzy.aopanno"/>
<!-- 开启Aspect生成代理对象-->
<aop:aspectj-autoproxy/>
准备工作做的差不多了,可以开始应用了,如果我们要对User类下的add方法加一个前置通知,也就是执行该方法前执行的操作,首先创建一个User类,并把该类注入到Spring
package com.hzy.aopanno;
import org.springframework.stereotype.Component;
@Component
public class User {
public void add() {
System.out.println("add ...");
}
}
然后是一个User的代理类,也就是负责通知的,这里的@Aspect就是切面,把该通知应用到切入点,其中execution(* com.hzy.aopanno.User.add(..))
代表对add方法进行切入,如果所有的方法切人是execution(* com.hzy.aopanno.User.*(..))
package com.hzy.aopanno;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class UserProxy {
@Before(value = "execution(* com.hzy.aopanno.User.add(..))")
public void before() {
System.out.println("before ...");
}
}
下面我们测试一下
import com.hzy.aopanno.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = context.getBean("user", User.class);
user.add();
}
}
然后我们再进行演示after和around
修改代理类
package com.hzy.aopanno;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class UserProxy {
@Before(value = "execution(* com.hzy.aopanno.User.add(..))")
public void before() {
System.out.println("before ...");
}
@After(value = "execution(* com.hzy.aopanno.User.add(..))")
public void after() {
System.out.println("after ...");
}
@Around(value = "execution(* com.hzy.aopanno.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕之前 ...");
proceedingJoinPoint.proceed();
System.out.println("环绕之后 ...");
}
}
观察测试结果会发现,在before之前会环绕,after之前也会环绕