权限切面和日志切面穿插在软件模块中,为原始业务代码添加额外的拓展,随称为面向切面编程
AOP的做法是将通用、与业务无关的功能抽象封装为切面类
切面可配置在目标方法的执行、执行后运行,真正做到即插即用。
AOP的最终目的:在不修改源码的情况下对程序行为进行拓展
1、引入依赖
org.springframework
spring-context
5.3.16
org.aspectj
aspectjweaver
1.9.5
2、模拟业务类
正常的一些dao/service
import org.springframework.stereotype.Component;
@Component
public class Say {
public String saying(String s ){
return "=========: "+ s;
}
}
3、定义Aspect切面类

package com.wasane.test1;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class SayAop {
@Pointcut("execution(public String com.study.test.Say.saying(..))")
public void a (){
}
@Before("a()")
public void before1(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
Object [] args = joinPoint.getArgs();
System.out.println(name+" before "+args[0]);
}
@After("a()")
public void after1(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
Object [] args = joinPoint.getArgs();
System.out.println(name+" after ,"+ args[0]);
}
@Around("a()")
public void aroud1(ProceedingJoinPoint joinPoint) throws Throwable {
String name = joinPoint.getSignature().getName();
System.out.println(name+" aroud start");
Object t = joinPoint.proceed();
System.out.println(name+" aroud return : "+ t);
System.out.println(name+" aroud end");
}
@AfterReturning(value = "a()" , returning = "return2")
public void return1(JoinPoint joinPoint , String return2){
String name = joinPoint.getSignature().getName();
System.out.println(name+" return :"+ return2 );
}
@AfterThrowing(value = "a()" , throwing = "excep")
public void exception1(JoinPoint joinPoint , Exception excep){
String name = joinPoint.getSignature().getName();
System.out.println(name+" Exception :"+ excep );
}
}
4、xml或这注解方法开启切面编程,因为spring是默认不开启的

或者
package com.wasane.test1;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com....")
public class MyConfig {
}
5、测试
import com.wasane.test1.MyConfig;
import com.wasane.test1.Say;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {MyConfig.class})
public class AopTest {
@Autowired
Say s ;
@Test
public void test1(){
System.out.println(s.saying(" gooos " ));
}
}
| 注解 | back |
|---|---|
| Aspect | 切面 |
| Target Class/Method | 目标类 |
| PointCut | 切入点 |
| JoinPoint | 连接点 |
| Advice | 通知 |
Aspect类的方法名随意,返回参数为void/Object,但是参数必须为(JoinPoint joinPoint);
joinPoint.getTarget();//从IOc容器内的目标对象
joinPoint.getSignature();//获取目标方法
joinPoint.getArgs();//获取目标
execution()表达式,规定Aspect表达式的应用类的范围
类修饰符public 返回值String 包范围-类名-方法名-方法的参数形式com.study.test.Say.saying(…)这个指的是saying方法所有参数形式都应用
@Pointcut("execution(public String com.study.test.Say.saying(..))")
Before Advice 前置通知 对应注解@Before
After Returning Advice 返回后通知
After Throwing Advice 异常通知
After Advice 后置通知
Around Advice环绕通知,最强大通知,自定义通知执行时机,可决定目标方法是否运行
Spring基于代理模式实现功能动态拓展AOP,包含两种形式:
1.目标类有接口,通过JDK动态代理实现功能拓展
2.目标类没有接口,通过CGLib组件实现功能拓展
CGLib
CGLib是运行时字节码增强技术
Spring AOP拓展无接口类使用CGLib
AOP会运行时生成目标继承类字节码的方式进行行为拓展