ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

【Spring】AOP的代理过程

【Spring】AOP的代理过程 目录一、AOP 三大概念二、AOP 的实现方式三、AOP 代理创建流程一、AOP 三大概念Spring AOP 有三个重要的组成部分Aspect、Pointcut、Advice。Advice 代表时间、Pointcut 代表位置Aspect 代表代理方法Advice通知/增强在特定的连接点执行的代码如前置通知、后置通知、环绕通知等Pointcut切点定义了通知应该在哪些连接点方法上生效Aspect切面一个模块化的横切关注点通常是一个类包含通知和切点二、AOP 的实现方式Spring AOP 的实现依赖于代理模式和动态代理技术。Spring 提供了两种主要的 AOP 实现方式基于 JDK 动态代理适用于目标对象实现了接口的情况基于 CGLIB 动态代理适用于目标对象没有实现接口的情况三、AOP 代理创建流程3.1、 Bean 初始化当你在 Spring 配置类中使用 EnableAspectJAutoProxy 注解时Spring 会导入 AspectJAutoProxyRegistrar 然后注册 AnnotationAwareAspectJAutoProxyCreatorAnnotationAwareAspectJAutoProxyCreator 实现了 BeanPostProcessor 接口。我们知道 BeanPostProcessor 是一个 Bean 声明周期接口所以在 Spring 生成 Bean 的时候会调用 AnnotationAwareAspectJAutoProxyCreator 的 postProcessBeforeInstantiation 方法来检查当前 Bean 是否需要被代理publicObjectpostProcessAfterInitialization(NullableObjectbean,StringbeanName){if(bean!null){ObjectcacheKeythis.getCacheKey(bean.getClass(),beanName);if(this.earlyProxyReferences.remove(cacheKey)!bean){// 检查当前 Bean 是否需要被代理returnthis.wrapIfNecessary(bean,beanName,cacheKey);}}returnbean;}3.2 wrapIfNecessary 方法wrapIfNecessary 方法判断 Bean 是否需要创建代理。如果当前 Bean 有适用的增强器则通过 createProxy 方法来实际创建代理对象protectedObjectwrapIfNecessary(Objectbean,StringbeanName,ObjectcacheKey){if(StringUtils.hasLength(beanName)this.targetSourcedBeans.contains(beanName)){returnbean;}elseif(Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))){returnbean;}elseif(!this.isInfrastructureClass(bean.getClass())!this.shouldSkip(bean.getClass(),beanName)){Object[]specificInterceptorsthis.getAdvicesAndAdvisorsForBean(bean.getClass(),beanName,(TargetSource)null);if(specificInterceptors!DO_NOT_PROXY){this.advisedBeans.put(cacheKey,Boolean.TRUE);Objectproxythis.createProxy(bean.getClass(),beanName,specificInterceptors,newSingletonTargetSource(bean));this.proxyTypes.put(cacheKey,proxy.getClass());returnproxy;}else{this.advisedBeans.put(cacheKey,Boolean.FALSE);returnbean;}}else{this.advisedBeans.put(cacheKey,Boolean.FALSE);returnbean;}}3.3 createProxy 方法createProxy 方法会根据目标类是否实现了接口来决定使用 JDK 动态代理还是 CGLIB 动态代理这样 Spring 生成的Bean 其实是经过 AOP 增强的 BeanprotectedObjectcreateProxy(Class?beanClass,NullableStringbeanName,NullableObject[]specificInterceptors,TargetSourcetargetSource){if(this.beanFactoryinstanceofConfigurableListableBeanFactory){AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory,beanName,beanClass);}ProxyFactoryproxyFactorynewProxyFactory();proxyFactory.copyFrom(this);if(proxyFactory.isProxyTargetClass()){if(Proxy.isProxyClass(beanClass)||ClassUtils.isLambdaClass(beanClass)){Class[]var6beanClass.getInterfaces();intvar7var6.length;for(intvar80;var8var7;var8){Class?ifcvar6[var8];proxyFactory.addInterface(ifc);}}}elseif(this.shouldProxyTargetClass(beanClass,beanName)){proxyFactory.setProxyTargetClass(true);}else{this.evaluateProxyInterfaces(beanClass,proxyFactory);}Advisor[]advisorsthis.buildAdvisors(beanName,specificInterceptors);proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);this.customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if(this.advisorsPreFiltered()){proxyFactory.setPreFiltered(true);}ClassLoaderclassLoaderthis.getProxyClassLoader();if(classLoaderinstanceofSmartClassLoaderclassLoader!beanClass.getClassLoader()){classLoader((SmartClassLoader)classLoader).getOriginalClassLoader();}returnproxyFactory.getProxy(classLoader);}
返回列表