一文搞懂Spring AOP源码底层原理

您所在的位置:网站首页 aop拦截service 一文搞懂Spring AOP源码底层原理

一文搞懂Spring AOP源码底层原理

2023-04-02 16:50| 来源: 网络整理| 查看: 265

一、什么是AOP

与OOP对比,AOP是处理一些横切性问题,这些横切性问题不会影响到主逻辑实现的,但是会散落到代码的各个部分,难以维护。一键获取源码地址spring aop面试题

AOP就是把这些问题和主业务逻辑分开,达到与主业务逻辑解耦的目的。

二、 AOP的应用场景

· 日志记录

· 权限验证

· 效率检查

· 事务管理

三、Spring AOP原理及其应用 3.1 AOP相关概念

· Aspect(切面): 通常是一个类(交给Spring容器管理),里面可以定义切入点和通知

· JointPoint(连接点): 程序执行过程中的一个点,如方法的执行或异常的处理

· Advice(通知): AOP在特定的切入点上执行的增强处理

· 通知类型:

· Before advice

· After returning advice

· After throwing advice

· After (finally) advice

· Around advice

· 调用顺序:

· Around advice>Before advice>After (finally) advice>After returning advice/After throwing advice

· Pointcut(切入点): 连接点的集合

· Target object(目标对象):被通知对象

· AOP proxy:AOP框架创建的对象,代理就是目标对象的增强。

· JDK dynamic proxy

· CGLIB proxy

· 思考: 初始化时织入还是获取对象时织入?

· Weaving(织入):把代理逻辑加入到目标对象上的过程叫做织入

3.2 AOP的应用 3.2.1 Spring AOP with AspectJ pointcuts Schema-based AOP Support

xml配置对AOP支持的 后置处理器

AspectJAwareAdvisorAutoProxyCreatorAnnotationAwareAspectJAutoProxyCreator // 配置 aop:aspectj-autoproxy/

spring-aop.xml

bat.ke.qq.com.config.XmlAspect"/>

public class XmlAspect { public void before(JoinPoint point) { System.out.println(“before”); } public void after() { System.out.println(“after”); }}

@AspectJ support

注解配置对AOP支持的 后置处理器

AnnotationAwareAspectJAutoProxyCreator

利用aspectj的注解

@[email protected] class AppConfig {}

@[email protected] class AspectConfig { //@Pointcut(“execution(* bat.ke.qq.com.dao.*.*(…))”) //@Pointcut(“within(bat.ke.qq.com.dao.*)”) //@Pointcut(“args(String)”) //@Pointcut(“this(bat.ke.qq.com.dao.FoxDao)”) // jdk动态代理 extend Proxy implements IFoxDao //@Pointcut(“target(bat.ke.qq.com.dao.FoxDao)”) //@Pointcut(“args(String …) || args()”) //@Pointcut(“execution(* bat.ke.qq.com.dao.*.*(String))”) //@Pointcut(“@annotation(bat.ke.qq.com.anno.Yuanma)”) //@Pointcut(“@target(bat.ke.qq.com.anno.Dao)”) // 目标是注解配置 //@Pointcut(“@within(bat.ke.qq.com.anno.Dao)”) //@Pointcut(“@args(bat.ke.qq.com.anno.Dao)”) //传参类型配置@Dao的类型 @Pointcut(“bean(foxDao)”) private void pointcut() { } @Before(“pointcut()”) public void before(JoinPoint point) { point.getThis(); System.out.println(“before”); } @After(“pointcut()”) public void after() { System.out.println(“after”); } @AfterReturning(“pointcut()”) public void afterReturning() { System.out.println(“afterReturning”); } @AfterThrowing(“pointcut()”) public void afterThrwoing() { System.out.println(“afterThrwoing”); } @Around(“pointcut()”) public Object around(ProceedingJoinPoint point) throws Throwable { System.out.println(“around”); Object[] args = point.getArgs(); for(int i=0;iAbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization>AbstractAutoProxyCreator#postProcessAfterInitialization> AbstractAutoProxyCreator#wrapIfNecessary> //创建代理对象Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

通过AopProxyFactory获取AopProxy

ProxyCreatorSupport#createAopProxy>DefaultAopProxyFactory#createAopProxy// JDK动态代理和Cglib的选择if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " +“Either an interface or a target is required for proxy creation.”); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config);}else { return new JdkDynamicAopProxy(config);}

JDK dynamic proxy

在Proxy这个类当中首先实例化一个对象ProxyClassFactory,然后在get方法中调用了apply方法,完成对代理类的创建

JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)> Proxy#newProxyInstance> Proxy# getProxyClass0proxyClassCache = new WeakCache(new KeyFactory(), new ProxyClassFactory());>ProxyClassFactory#apply// generateProxyClass: 通过反射收集字段和属性然后生成字节码byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags);// defineClass0: jvm内部完成对上述字节码的loadreturn defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);

CGLIB proxy

cglib封装了ASM这个开源框架,对字节码操作,完成对代理类的创建。主要通过集成目标对象,然后完成重写,再操作字节码。

org.springframework.aop.framework.CglibAopProxy#getProxy(java.lang.ClassLoader)

总结:

cglib是通过继承来操作子类的字节码生成代理类,JDK是通过接口,然后利用java反射完成对类的动态创建,严格意义上来说cglib的效率高于JDK的反射,但是这种效率取决于代码功力,其实可以忽略不计。

添加 博主 获取试题


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3