目录
一、AOP概述
AOP(Aspect Oriented Programming):面向切面编程;将程序重复的代码抽取出来,执行时,使用动态代理的技术,在不修改源码的基础上,对已有方法进行增强。
相关术语
名称 | 功能 |
---|---|
连接点(Joint Point) | 连接点是指那些被拦截的方法 |
切入点(Pointcut) | 切入点是指对Jointpoint进行拦截的定义 |
通知(Advice) | 通知是指拦截到Joinpoint之后所要做的事情 |
目标对象(Target) | 被代理的对象 |
代理(Proxy) | 增强后的对象 |
切面(Aspect) | 切入点和通知的结合 |
二、整合AOP
2.1 导入jar包
导入aop相关的jar包:
aopalliance-1.0.jar
aspectjweaver-1.9.4.jar
spring-aop-5.1.9.RELEASE.jar
spring-aspects-5.1.9.RELEASE.jar
或者使用maven导入依赖包
<!--spring-aop-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.9.RELEASE</version>
</dependency>
<!--spring-aspects-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.9.RELEASE</version>
</dependency>
<!--aopalliance-->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<!-- aspectjweaver-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
Spring4之后和2.5发生了很大的变化,原来的spring2.5很多倚赖的jar包都是随着spring一起发布的,现在spring4之后的版本已经不再发布倚赖包,需要自己导入;
2.2 开启支持
在配置文件中开启aop的支持;
<aop:aspectj-autoproxy/>
2.3 定义切面类
创建切面类,并设置通知方法
@Component
@Aspect
public class UserLog {
@Before("execution(* com.spring.bean.UserBean.work(..))")
public void Before(){
System.out.println("前置通知...");
}
}
2.4 测试
public class userTest {
@Test
public void test(){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("SpringConfig.xml");
UserBean userBean = (UserBean) ac.getBean("userBean");
userBean.work();
}
}
执行结果:
三、使用注解
3.1 常用注解
-
@Aspect 把当前类声明为切面
-
@Before(value=“切入表达式”) 把当前方法设置为前置通知
-
@AfterReturning(value=“切入表达式”) 把当前方法设置为后置通知
-
@After(value=“切入表达式”) 把当前方法设置为最终通知
-
@AfterThrowing(value=“切入表达式”) 把当前方法设置为异常通知
-
@Around 把当前方法设置为环绕通知,即@Before和@After的结合
-
@Pointcut(value=“切入表达式”) 指定切入表达式
3.2 @AfterReturning和@After的区别
1)它们都是在切入方法执行完成后执行,但是@AfterReturning在@After之后执行;
2)如果方法出现异常,那么@AfterReturning将不会执行;而@After无论方法是否正常结束,它都会被执行;
3)@AfterReturning可以访问目标方法的返回值,而@After就无法做到;
@AfterReturning(value="execution(* com.xjy.service.impl.*.*(..))", returning="rt")
public void afterReturn(Object rt) throws Throwable {
System.out.println("切入方法的返回值:" + rt);
System.out.println("方法返回通知...");
}
注意:returning属性值要与方法的参数名相同。
3.3 切入表达式
切入点表达式语法:
//1、拦截所有public方法
execution(public * *(..))
//2、拦截所有save开头的方法
execution(* add*(..))"
//3、拦截指定类的指定方法, 拦截时候一定要定位到方法
execution(* com.tung.dao.UserDao.add(..))
//4、拦截指定类的所有方法
execution(* com.tung.dao.UserDao.*(..))
//5、拦截指定包,以及其自包下所有类的所有方法
execution(* com..*.*(..))
//6、多条件
// 或:|| or
execution(* com.tung.dao.UserDao.add(..)) || execution(* com.tung.dao.AccountDao.add(..))
execution(* com.tung.dao.UserDao.add(..)) or execution(* com.tung.dao.AccountDao.add(..))
//且:&& and
execution(* com.tung.dao.UserDao.add(..)) && execution(* com.tung.dao.AccountDao.add(..)
execution(* com.tung.dao.UserDao.add(..)) and execution(* com.tung.dao.AccountDao.add(..)
//7、取非值:! not
!execution(* com.tung.dao.UserDao.add(..))"
//注意not前必须有空格
not execution(* com.tung.dao.UserDao.add(..))"
四、零配置(无配置文件)
- 创建配置类
- 使用@Configuration注解,指定Spring容器从当前类中加载读取配置信息即可实现零配置;
- 使用@ComponentScan注解,指定spring容器初始化时候要扫描的包;
- 使用@EnableAspectJAutoProxy注解,启用aop功能。
@Configuration
@ComponentScan(basePackages = {"com.spring"})
// 启用aop功能
@EnableAspectJAutoProxy
public class SpringConfig {
}