Spring AOP笔记

学习地址:慕课网

AOP

面向切面编程是一种编程范式,用来解决特定问题,是OOP的补充

使用初衷

这里写图片描述
这里写图片描述

AOP使用场景

这里写图片描述

1-权限案例对比

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

普通方法拦截

校验权限的一个例子

@Service
public class ProductService {

    @Autowired
    AuthService authService;

    public void insert(Product product){
        authService.checkAccess();//代码有侵入
        System.out.println("insert product");
    }

    public void delete(Long id){
        authService.checkAccess();
        System.out.println("delete product");
    }
}

AOP拦截方式

定义一个在方法上的注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AdminOnly {
}

在目标方法上加入注解

    @AdminOnly
    public void insert(Product product){
        //authService.checkAccess();代码有侵入
        System.out.println("insert product");
    }
    @AdminOnly
    public void delete(Long id){
        //authService.checkAccess();
        System.out.println("delete product");
    }

声明一个AOP,配置拦截规则

@Aspect
@Component
public class SecurityAspect {
    @Autowired
    AuthService authService;

    @Pointcut("@annotation(AdminOnly)")
    public void adminOnly(){

    }

    @Before("adminOnly()")//方法之前执行
    public void check(){
        authService.checkAccess();
    }
}

相对于普通方法,AOP的方式减少了重复代码,降低了代码耦合,更低的代码侵入性。

2-SpringAOP使用详解

这里写图片描述

@Aspect表示类是一个切面类
@Pointcut表示切面的作用范围
Advice表示作用的时间点,before、after

这里写图片描述

designators匹配的方式
wildcards匹配的通配符

* 匹配任意数量的字符
+匹配制定类及其子类
..一般用于匹配任意数的子包或参数

operators运算符

这里写图片描述

execution类型

@Aspect
@Component
public class ExecutionAspectConfig {

    //@Pointcut("execution(public * com.imooc.aopdemo.service.*Service.*(..))") 不拦截子包
    //@Pointcut("execution(public * com.imooc.aopdemo.service..*Service.*(..))")

    //@Pointcut("execution(public void com.imooc.aopdemo.service..*Service.*(..))") //匹配返回值为void的方法
    //@Pointcut("execution(public * com.imooc.aopdemo.service..*Service.*(Long))") //匹配第一个参数为Long的方法
    //@Pointcut("execution(public * com.imooc.aopdemo.service..*Service.*())") //匹配没有参数的方法
    @Pointcut("execution(public * com.imooc.aopdemo.service..*Service.*(..) throws IllegalAccessException)") //匹配抛出异常的方法
    public void matchCondition(){

    }

    @Before("matchCondition()")
    public void before(){
        System.out.println("");
        System.out.println("***before***");
    }
}

within类型

@Aspect
@Component
public class PkgTypeAspectConfig {
  //@Pointcut("within(com.imooc.aopdemo.service.ProductService)")匹配类里的所有方法
    @Pointcut("within(com.imooc.aopdemo.service..*)")//匹配ProductService类里头的所有方法
    public void matchType(){}

    @Before("matchType()")
    public void before(){
        System.out.println("");
        System.out.println("***before***");
    }
}

对象匹配

argetthis的区别:
this能够拦截AOPintroduction定义的方法,而target不行(因为intrduction定义的方法是经过AOP代理过后动态添加的)
这里写图片描述

参数匹配

这里写图片描述

注解匹配

这里写图片描述

@Aspect
@Component
public class AnnoAspectConfig {

    //@Pointcut("@annotation(com.imooc.aopdemo.anno.AdminOnly)")
    //@Pointcut("@within(com.imooc.aopdemo.anno.NeedSecured) && within(com.imooc.aopdemo..*)")
    //@Pointcut("@target(com.imooc.aopdemo.anno.NeedSecured) && within(com.imooc.aopdemo..*)")
    @Pointcut("@args(com.imooc.aopdemo.anno.NeedSecured) && within(com.imooc.aopdemo..*)")
    public void matchCondition(){

    }
    @Before("matchCondition()")
    public void before(){
        System.out.println("");
        System.out.println("***before***");
    }
}

advice注解

这里写图片描述

@Aspect
@Component
public class AdviceConfig {
    @Pointcut("@annotation(com.imooc.aopdemo.anno.AdminOnly)")
    public void matchAnno(){}

    @Pointcut("execution(* *..find*(Long,..))")
    public void matchLongArg(){}

    @Pointcut("execution(* *..*(..)throws IllegalAccessException)")
    public void matchException(){}

    @Pointcut("execution(String com.*..*(..))")
    public void matchReturn(){}

    @Pointcut("execution(* com.*..*(..))")
    public void matchAll(){}

//    @Around("matchReturn()")
//    public void around(ProceedingJoinPoint joinPoint){
//        try{
//            Object res = joinPoint.proceed(joinPoint.getArgs());
//            System.out.println("==========return data:"+res);
//        } catch (Throwable throwable) {
//            throwable.printStackTrace();
//        } finally {
//            System.out.println("===========finally================");
//        }
//    }

//    @Before("matchLongArg() && args(ww,..)")
//    public void before(long ww){
//        System.out.println("==========the data:"+ww);
//    }

    @AfterThrowing("matchException()")
    public void after(){
        System.out.println("=========after========");
    }
}

3-SpringAOP实现原理

代理模式(静态代理)

接口

public interface Subject {
    void request();

}

目标对象

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("real subject excute request");

    }
}

代理对象

public class Proxy implements Subject {
    private RealSubject realSubject;

    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        System.out.println("before");
        try {
            realSubject.request();
        } catch (Exception e) {
            System.out.println("ex:"+e.getMessage());
            throw e;
        }finally {
            System.out.println("after");
        }
    }
}

客户端调用

public class Client {
    public static void main(String args[]){
        Subject subject = new Proxy(new RealSubject());//通过构造器强行注入
        subject.request();
    }
}

jdk代理

这里写图片描述

/**
 * jdk动态代理
 *
 */
public class JdkProxySubject implements InvocationHandler {

    private RealSubject realSubject;

    public JdkProxySubject(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before");
        Object result = null;
        try {
            result = method.invoke(realSubject,args);

        } catch (Exception e) {
            System.out.println("ex:"+e.getMessage());
            throw e;
        }finally {
            System.out.println("after");
        }
        return result;
    }
}
public class Client {
    public static void main(String args[]){
        Subject subject = (Subject) Proxy.newProxyInstance(Client.class.getClassLoader()
        ,new Class[]{Subject.class},new JdkProxySubject(new RealSubject()));
        subject.request();
    }
}

接口增加方法,静态代理需要实现其接口,而动态代理不需要改动代码。

public interface Subject {
    void request();
    void hello();
}

cglib代理

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
public class DemoMethodInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before in cglib");
        Object result = null;
        try {
            result = methodProxy.invokeSuper(o,objects);
        }catch (Exception e){
            System.out.println("ex:"+e.getMessage());
            throw e;
        }finally {
            System.out.println("after in cglib");
        }
        return result;
    }
}
public class Client {
    public static void main(String args[]){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(RealSubject.class);
        enhancer.setCallback(new DemoMethodInterceptor());
        Subject subject = (Subject) enhancer.create();
        subject.hello();
    }
}

这里写图片描述

AOP如何链式调用

这里写图片描述

public abstract class Handler {

    private Handler sucessor;

    public void execute(){
        //链式调用
        handleProcess();
        if(sucessor != null){
            sucessor.execute();
        }
    }

    protected abstract void handleProcess();

    public Handler getSucessor() {
        return sucessor;
    }

    public void setSucessor(Handler sucessor) {
        this.sucessor = sucessor;
    }

}
public class Client {
    static class  HandlerA extends Handler{

        @Override
        protected void handleProcess() {
            System.out.println("handler by a");
        }
    }
    static class  HandlerB extends Handler{

        @Override
        protected void handleProcess() {
            System.out.println("handler by b");
        }
    }
    static class  HandlerC extends Handler{

        @Override
        protected void handleProcess() {
            System.out.println("handler by c");
        }
    }
    public static void main(String args[]){
        Handler handlerA = new HandlerA();
        Handler handlerB = new HandlerB();
        Handler handlerC = new HandlerC();

        handlerA.setSucessor(handlerB);
        handlerB.setSucessor(handlerC);
        handlerA.execute();
    }
}

第二种方式:

public class Chain {
    private List<ChainHandler> handlers;

    private int index = 0;

    public Chain(List<ChainHandler> handlers) {
        this.handlers = handlers;
    }
    public void proceed(){
        if(index >= handlers.size()){
            return ;
        }
        handlers.get(index++).execute(this);
    }
}
public abstract class ChainHandler {

    public void execute(Chain chain){
        handleProcess();
        chain.proceed();//执行表下一个Chain
    }
    protected abstract void handleProcess();
}
public class ChainClient {

    static class ChainHandlerA extends ChainHandler{
        @Override
        protected void handleProcess() {
            System.out.println("handle by chain a ");
        }
    }
    static class ChainHandlerB extends ChainHandler{
        @Override
        protected void handleProcess() {
            System.out.println("handle by chain b ");
        }
    }
    static class ChainHandlerC extends ChainHandler{
        @Override
        protected void handleProcess() {
            System.out.println("handle by chain c ");
        }
    }
    static class ChainHandlerD extends ChainHandler{
        @Override
        protected void handleProcess() {
            System.out.println("handle by chain d ");
        }
    }
    public static void main(String args[]){
        List<ChainHandler> handlers = Arrays.asList(
                new ChainHandlerA(),new ChainHandlerB(),
                new ChainHandlerC(),new ChainHandlerD()
        );
        Chain chain = new Chain(handlers);
        chain.proceed();
    }

}

Spring AOP注解

这里写图片描述

对单个数据库操作有事务控制,同一个方法内有多个数据库操作,不加事务注解,各自的事务不会相互影响;加上注解,会加上一个事务包含这些事务,对每个事务进行标记,当所有事务执行完之后,根据标记判断执行还是回滚

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值