# 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(); } } ## 其它的知识