Spring AOP

Srping AOP

AOP:ASpect Oriented Programming 面向切面编程

代理模式

拦截器 ,过滤器,单例模式,简单工厂模式

静态代理:

在这里插入图片描述

让目标对象和代理实现同一个接口,目的是让客户端访问的时候行为一致。
在代理对象里面转调目标对象之前和之后做一些事情。方便为原有的功能添加新的功能。
Proxy:代理对象,通常有以下功能:
1、实现和具体的目标对象一样的接口,这样可以使用代理来代替具体的目标对象。
2、保存一个具体目标对象的引用,需要时可以调用具体的目标对象方法。
3、可以控制对具体目标对象的的访问。权限控制、日志处理。

public interface IQianZi {
  public void qianzi();
}
public class DongShiZhang implements IQianZi{
  @Override
  public void qianzi() {
    System.out.println("DongShiZhang.qianzi()");
  }
}
public class MiShu implements IQianZi{
  private DongShiZhang dongShiZhang;
  
  public MiShu(DongShiZhang dongShiZhang) {
    this.dongShiZhang = dongShiZhang;
  }
  
  @Override
  public void qianzi() {
    // 判断是否合法
    System.out.println("MiShu.qianzi() befoe    开启事物");
    dongShiZhang.qianzi();
    System.out.println("MiShu.qianzi() after    事物关闭");
    // ...
  }
}
public class Client {
  
  public static void main(String[] args) {
    DongShiZhang dongShiZhang = new DongShiZhang();
    IQianzi miShu = new MiShu(dongShiZhang);
    miShu.qianzi();
  }
}
MiShu.qianzi() befoe
DongShiZhang.qianzi()
MiShu.qianzi() after

静态代理:
优点:可以做到不修改目标对象的前提下,对目标对象的功能进行扩展(目标对象董事长只要关注签字,像开启事物和关闭事物的操作都交给秘书处理)。
缺点:
1、代理对象和目标对象实现相同的接口,有一个目标对象就要有一个代理对象,会产生很多代理类,类太多。
2、一旦接口增加方法,目标对象和代理对象都要去维护。

动态代理(JDK代理):
1)不需要自己写代理对象,但是目标对象还是需要实现接口;
2)代理对象的生成,是利用JDKAPI, 动态的在内存中构建代理对象(需要我们指定创建 代理对象/目标对象 实现的接口的类型;);
3)  动态代理也叫:JDK代理,接口代理;
public class ProxyFactory {
  /**
   * 得到代理对象
   * @param object 目标对象
   * @return 代理对象
   */
  public static Object getProxyInstance(Object target) {
    return Proxy.newProxyInstance(
         target.getClass().getClassLoader(), // 指定目标对象使用的类加载器
         target.getClass().getInterfaces(), // 目标对象实现的接口
         new InvocationHandler() { // 事件处理器
           
           // Object proxy 代理对象
           // Method method 调用的方法 
           // Object[] args 调用的方法的参数
           @Override
           public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
             System.out.println("开启事物");
             Object returnValue = method.invoke(target, args);
             System.out.println("关闭事物");
             return returnValue;
           }
         });
  }
}

// 目标对象
IQianZi target = new DongShiZhang();
// 给目标对象创建代理对象
IQianZi proxy = (IQianZi) ProxyFactory.getProxyInstance(target);
proxy.qianzi();

动态代理的优点和缺点:
优点:不需要自己去创建代理类。
缺点:但是目标对象一定要实现接口,否则不能用动态代理。

AOP为Aspect Oriented Programming

Aspect:切面
OOP:面向对象编程 Object Oriented Programming

AOP中注解的含义
@Aspect:切面。
表示一个横切进业务的一个对象。它里面包含切入点(Pointcut)+Advice(通知)。
@Pointcut:切入点。
表示需要切入的位置,比如某些类或者某些方法,也就是先定一个范围。

AOP通知:
1、前置通知@Before:在方法调用之前执行
2、后置通知@AfterReturning:在方法正常调用之后执行
3、环绕通知@Around:在方法调用之前和之后,都分别可以执行的通知
4、异常通知@AfterThrowing:如果在方法调用过程中发生异常,则通知
5、最终通知 @After:在方法调用之后执行,类似于finally
.
在这里插入图片描述

package com.situ.springboot.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

// 需要引入aop依赖:spring-boot-starter-aop
//<dependency>
//  <groupId>org.springframework.boot</groupId>
//  <artifactId>spring-boot-starter-aop</artifactId>
//</dependency>
// Aspect 切面
@Aspect
@Component
public class ServiceLogAspect {
    public static final Logger log =
            LoggerFactory.getLogger(ServiceLogAspect.class);
    /**
     * 切面表达式:
     * execution 代表所要执行的表达式主体
     * 第一处 * 代表方法返回类型, *代表所有类型
     * 第二处 包名代表aop监控的类所在的包
     * 第三处 .. 代表该包以及其子包
     * 第四处 * 代表类名,   *代表所有类
     * 第五处 *(..) *代表类中的方法名,(..)表示方法中的任何参数
     */
    @Around("execution(* com.situ.springboot.service.impl..*.*(..))")
    public Object recordTimeLog(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("ServiceLogAspect.recordTimeLog");
        // {}是占位符
        log.info("====== 开始执行 {}.{} ======",
                joinPoint.getTarget().getClass(),
                joinPoint.getSignature().getName());

        // 记录开始时间
        long begin = System.currentTimeMillis();

        // 执行目标 service
        Object result = joinPoint.proceed();

        // 记录结束时间
        long end = System.currentTimeMillis();
        long takeTime = end - begin;
        if (takeTime > 3000) {
            log.error("====== 执行结束,耗时:{} 毫秒 ======", takeTime);
        } else if (takeTime > 2000) {
            log.warn("====== 执行结束,耗时:{} 毫秒 ======", takeTime);
        } else {
            log.info("====== 执行结束,耗时:{} 毫秒 ======", takeTime);
        }

        return result;
    }
}



@Aspect
class TransactionDemo {
    @Pointcut(value="execution(* com.situ.springboot.service.*.*.*(..))")
    public void point(){
    }

    @Before(value="point()")
    public void before(){
        System.out.println("transaction begin");
    }

    @AfterReturning(value = "point()")
    public void after(){
        System.out.println("transaction commit");
    }

    @Around("point()")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("transaction begin");
        joinPoint.proceed();
        System.out.println("transaction commit");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值