AOP(Aspect Oriented Programming ) 面向切面 编程 , 一 种编程范式,指导开发者如何组织程序 结构-- OOP(Object Oriented Programming) 面向对象编程作用:在不惊动原始设计的基础上为其进行功能增强Spring 理念:无入侵式 / 无侵入式
本讲解基于全注解开发
AOP也是一种思想,做的是解耦操作,把一系列的重复操作提取出来,更方便更改。尤其是做外卖的日志操作。
入门案例一:在接口执行前输出当前系统时间:对update进行增强
注意我专门写了一个SpringConfig类进行全注解开发,这是一个配置类
第三个注解@EnableAspectJAutoProxy 是告诉Spring识别切面类
切面类:
@Component
@Aspect
public class MyAdvice {
//随便定义一个无参无方法体的方法
//设置切入点
@Pointcut("execution(void com.gsdx.dao.BookDao.update())")
private void pt(){}
//设置在切入点前执行
@Before("pt()")
public void method(){
System.out.println(System.currentTimeMillis());
}
}
测试类
public class App
{
public static void main( String[] args )
{
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = ctx.getBean(BookDao.class);
bookDao.update();
}
}
测试结果
update执行前,当前时间已经输出了
AOP工作流程
代理对象简单理解的话就是继承了BookDaoImpl,然后在方法执行前执行abefore方法,这是片面的理解
通知类型
我们就来讲一下环绕通知
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around before advice ...");
Object ret = pjp.proceed();
System.out.println("around after advice ...");
return ret;
}
这是BookDao中有返回参数的写法,返回Object,里面要用到ProceedingJoinPoint类
案例2:测量业务层接口万次执行效率
简单的说就是测量业务层某接口执行前后的时间,我们肯定要用到around环绕通知
@Around("ProjectAdvice.servicePt()")
public void runSpeed(ProceedingJoinPoint pjp) throws Throwable {
//获取执行签名信息
Signature signature = pjp.getSignature();
//通过签名获取执行类型(接口名)
String className = signature.getDeclaringTypeName();
//通过签名获取执行操作名称(方法名)
String methodName = signature.getName();
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
pjp.proceed();
}
long end = System.currentTimeMillis();
System.out.println("万次执行:"+className+"."+methodName+"--->"+(end-start)+"ms");
}
pjp.proceed表示的是去执行接口中的方法
案例3:百度网盘密码数据兼容处理
案例先知:AOP通知获取数据
这里获取的是接口中方法的形参的值
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
System.out.println(Arrays.toString(args));
Object ret = pjp.proceed();
return ret;
}
思路是通过环绕通知,先对url,password进行处理,再执行pjp.proceed();
@Repository
public class ResourcesDaoImpl implements ResourcesDao {
public boolean readResources(String url, String password) {
System.out.println(password.length());
//模拟校验
return password.equals("root");
}
}
@Component
@Aspect
public class DataAdvice {
@Pointcut("execution(boolean com.itheima.service.*Service.*(*,*))")
private void servicePt(){}
@Around("DataAdvice.servicePt()")
public Object trimStr(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
for (int i = 0; i < args.length; i++) {
//判断参数是不是字符串
if(args[i].getClass().equals(String.class)){
args[i] = args[i].toString().trim();
}
}
Object ret = pjp.proceed(args);
return ret;
}
}