# spring-02-aop
**Repository Path**: stevenye/spring-02-aop
## Basic Information
- **Project Name**: spring-02-aop
- **Description**: spring aop学习和使用
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2017-01-10
- **Last Updated**: 2020-12-18
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Spring framework AOP的使用
## 基本概念
### Advice(通知)
> 解释:从多个组件中抽出的需要被复用的代码或功能,换句话说,就是切面需要做的操作[what to do]
## Weave(织入)
> 解释:将Advice中的代码或功能,应用到各组件的过程,这个过程一般无需我们参与,由spring内部完成或是借助第三方完成,了解即可。
## JointPoint(连接点)
> 解释:以方法为单元,定义Advice可以织入的点,也就是包装了被织入的类的方法的对象,通过连接点,可以获取被织入对象的类型和方法
> 如:
> jp.getTarget().getClass() //获取被织入的类名
> jp.getSignature().getName() //获取方法名
## PointCut(切入点)
解释:用表达式定义一组 JoinPoint 的集合,它表达的是何时切入,支持如下5种时机
* @Before 在方法运行之前切入
* @After 在方法运行之后切入,无论方法执行成功或异常
* @AfterReturning 在方法成功运行之后切入
* @AfterThrowing 在方法出现异常之后切入
* @Around 在方法运行前后切入
## Aspect(切面)
> 解释:声明一个切面,是一组关注点的模块化,是一个总称, Aspect=Advice \+ PointCut,也就是在何时(pointcut)织入何物(advice)
## 开发流程
1. 建立项目
2. 配置Spring框架依赖
3. 将需要被切割的组件,和负责切的组件部署到spring
4. 写配置信息类 AppConfig
5. 写单元测试类
### 配置信息类 AppConfig中,需要使用的注解有:
> @Configuration 表示这是个配置类
> @ComponentScan 扫描当前包及其子包中的加了相关注解的类
> @EnableAspectJAutoProxy 启用AspectJ的自动代理机制
@Configuration
@ComponentScan
@EnableAspectJAutoProxy //启用AspectJ AOP功能
public class AppConfig {
}
### 被切的组件,仍然通过@Component注解配置到SPRING 容器中
@Component
public class ClassA {
public String a(String str) {
System.out.println("a 方法的核心逻辑");
return "ok";
}
}
### 开发Advice类,也就是织入什么,当然,这个类也要使用@Component注解,它也必需被容器管理
@Component
@Aspect
public class MyLogAdvice {
@Before("execution(public * com.tz.xx.XXXClass.*(..))")
public void log(JoinPoint jp) {
String className = jp.getTarget().getClass().getSimpleName(); //
String methodName = jp.getSignature().getName();
System.out.printf("%s类的%s方法执行之前:%s\n",className,methodName,new Date());
}
}
### 有关AOP的切入点的表达式
**execution()切点函数**
> execution(public * *(..)) //匹配所有目标类的public方法
execution(* com.tz.spring.MyService.*(..)) //匹配指定包下的MyService类型中的所有方法
**注:如果要匹配所有的访问修饰符,不写即可(千万不要用 \* 号替代)**
execution(* com.tz.spring.*(..)) //匹配指定包下的所有类的所有方法
execution(* com.tz..*(..)) //匹配com.tz包、子孙包下的所有类的所有方法
execution(* com...*.*Dao.get*(..)) //匹配包名前缀为com的任何包下类名后缀为Dao,并且方法名必需以 get开头的方法
**@annotation() 指定注解**
> 任何标注了指定注解的目标方法连接点
**args()**
> 目标类方法运行时参数的类型指定连接点
**@args()**
> 目标类方法参数中是否有指定特定注解的连接点
**within()**
> 匹配指定的包的所有连接点
**target()**
> 匹配指定目标类的所有方法
**@within()**
> 匹配目标对象拥有指定注解的类的所有方法
**@target()**
> 匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解
**this()**
> 匹配当前AOP代理对象类型的所有执行方法
## AOP的**XML**配置
1. 首先得准备一个 spring框架的配置文件
2. 其次,在配置文件中使用AOP的配置
3. 配置AOP的advice
4. 配置AOP的pointcut
## AOP的测试
### 有两种方式
1. 不采用继承的方式,直接通过手动编写代码来完成
public class AppConfigManualTest {
@Test
public void testAop() throws Exception {
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
//
IHello h = (IHello)ac.getBean("hello");
//
String result = h.sayHi("jack");
//
System.out.println(result);
}
}
2. 继承Spring框架提供的测试类,并自动注入
@ContextConfiguration(classes = AppConfig.class)
public class AppConfigSpringTest extends AbstractTestNGSpringContextTests {
@Autowired
private IHello hello;
@Autowired
private AnnotationAOP aop;
@Test
public void testAop() throws Exception {
String result = hello.sayHi("Ann");
System.out.println("在测试方法中:"+result);
System.out.println("=======================================================");
aop.annotation();
}
}
## 其它的知识