Spring AOP 原理解析

AOP概述

AOP是什么

  • AOP是一种编程范式
  • 解决特定问题
  • 是OOP的补充

AOP的优势

  • 解决重复性代码
  • 关注点分离(集中处理某一关注点/横切逻辑)
  • 水平分离:展示层、服务层、持久层
  • 垂直分离:模块划分(订单、库存等)
  • 切面分离:分离功能性需求与非功能性需求
  • 可以很方便添加/删除关注点
  • 代码入侵少,增强代码可读性和可维护性

应用场景

  • 权限控制
  • 缓存控制
  • 事务控制
  • 审计日志
  • 性能监控
  • 分布式追踪
  • 异常处理

AOP的使用

使用方式

  • 基于XML
  • 基于注解

三大注解

  • @Aspect:标识类为切面类
  • @Pointcut:描述在哪些类哪些方法执行切面方法
  • Advice:执行方法的时机

切面表达式(Pointcut Expression)

  • 指示器(designators)
    《Spring AOP 原理解析》
  • within表达式(包匹配)
    《Spring AOP 原理解析》
  • 对象匹配
    《Spring AOP 原理解析》
  • 参数匹配
    《Spring AOP 原理解析》
  • 注解匹配
    《Spring AOP 原理解析》
  • execution表达式
    《Spring AOP 原理解析》
  • modifier-pattern 修饰符
  • ret-type-pattern!! 返回值
  • declaring- type-pattern 包名
  • name-pattern(param-pattern)!! 方法名(参数名)
  • throws-pattern (抛出异常)
  • 注:1. 有!!的不可省略 2.支持通配符
    《Spring AOP 原理解析》
  • advice注解
    《Spring AOP 原理解析》
  • 通配符(wildcards)
  • * :匹配任意数量的字符
  • + :匹配指定类及其子类
  • … :一般用于匹配任意数的子包或参数
  • 运算符(operators)
  • && :与
  • || :或
  • ! :非

AOP实现原理

  • 织入(Weaving),AOP术语。把切面(aspect)连接到其它的应用程序类型或者对象上,并创建一个被通知(advised)的对象,这样的行为叫做织入。

  • 织入时机
    《Spring AOP 原理解析》

  • 运行时织入使用代理对象实现

代理模式

《Spring AOP 原理解析》

代理对象将目标方法交给目标对象执行,本身执行额外的逻辑方法。

静态代理

  • 建一个接口,接口中定义相应(代理对象和目标对象都要实现)的 方法
public interface Subject{
void test();
}
  • 目标类(实现上述接口)
public class RealSubject implements Subject{
	@Override
	public void tset(){
	System.out.printin("Object Class");
	}
}
  • 代理类(实现上述接口)
public class Proxy implements Subject{
	private RealSubject realSubject;
	
	public Proxy(RealSubject realSubject){
	this.realSubject = realSubject;
	}


	@Override
	public void test(){
	System.out.printin("Before");
	try{
	realSubject.test();
	}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.test();
}
}

动态代理

(静态代理缺点:不灵活,重复代码多)

  • 基于接口代理(jdk)
  • 类:java.lang.reflect.Proxy(通过该类动态生成代理类)
  • 代理类实现接口:InvocationHandler
  • 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;
    }
    }

  • 客户端调用(使用Proxy)
  public class Client{
  public static void main(String[] args){
    //使用Proxy构造对象
    //参数
    //java泛型需要转换一下
    Subject subject = (Subject) java.lang.reflect.Proxy.newProxyInstance(Client.class.getClassLoader(),new Class[]{Subject.class},new JdkProxySubject(new RralSubject()));
    //调用方法
    subject.test;
    }
    }
  • 原理解析
  • 调用Proxy.newProxyInstance生成代理类的实现类:
  • 调用getProxyClass0//寻找或生成指定代理类
    (从缓存中取,如果没有,就生成一个放在缓存中。通过ProxyClassFactory生成)
  • 缓存调用ProxyClassFactory生成代理类
  • ProxyGenerator使用生成的代理类的名称,接口,访问标志生成proxyClassFile字节码
  • newInstance(生成字节码之后利用反射生成实例)
  • 基于继承代理(cglib)
  • 代理类
 public class CglibMethodInterceptor implements MethodInterceptor{
        @Override
        public Object intercept(Object obj,Method method,Object
        [] args,MethodProxy proxy )throws Throwable{
        System.out.println("before cgpib");
        Object result = null;
            try{
               //利用反射创建代理对象 
               result = proxy.invokeSuper(obj,args);
            }catch(Exception e){
            System.out.println("ex:"+e.getMessage());
                throw e;
            }finally{
                System.out.println("after cglib");
            }
            return result;
            }
        }
    
  • 调用类
 public class Client{
    public static void main(String[] args){
    //生成
    Enhancer enhancer=new Enhancer;
    //目标类
    enhancer.setSuperclass(RealSubject.class);
    //代理类
    enhancer.setCallback(new CglibMethodInterceptor());
    //生成代理类对象
    Subject subject=enhancer.create();
    subject.hello;
    }
}
  • 两种动态代理的对比和选择
    《Spring AOP 原理解析》

《Spring AOP 原理解析》
《Spring AOP 原理解析》
《Spring AOP 原理解析》
《Spring AOP 原理解析》

AOP链式调用

  • 责任链模式
    《Spring AOP 原理解析》
  • Chain类:
import java.util.List;
public class Chain{
    private List<ChainHandler> handlers;
    private int index = 0;
    //构造器
    public Chain(List<ChainHandler> handlers){
        this.handlers = handlers;
    }
        public void procceed(){
        	if(index >= handlers.size()){
        		return ;
        	}
        if(index >= handlers.size()){
            return ;
        }
        handlers.get(index++).execute(this);
    }
}
  • ChainHandler类:
public abstract class ChainHandler{
public void execute(Chain chain){
handlerProcess();
chain.procceed();
}
//抽象方法
protected abstract void handlerProcess();
}
  • ChainClient类:
import java.util.Arrays;
import java.util.List;

public class ChainClient{
static class ChainHandlerA extends ChainHandler{
    @Override
    protected void handlerProcess(){
        System.out.println("Chain A");
    }
}
static class ChainHandlerB extends ChainHandler{
    @Override
    protected void handlerProcess(){
        System.out.println("Chain B");
    }
}
static class ChainHandlerC extends ChainHandler{
    @Override
    protected void handlerProcess(){
        System.out.println("Chain C");
    }
}
public static void main(String[] args){
//声明链式关系
    List<ChainHandler> handler = Arrays.asList(new ChainHandlerA(),new ChainHandlerB(),new ChainHandlerC());
    Chain chain = new Chain(handler);
    chain.procceed();
}
}

AOP注意事项

《Spring AOP 原理解析》

文章目录

喜欢的话可以点点关注,或者添加作者微信,欢迎随时来撩
《Spring AOP 原理解析》

    原文作者:AOP
    原文地址: https://blog.csdn.net/weixin_40573194/article/details/82379149
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞