Spring-AOP模块的Advised分析
UML结构图如下:
Advised:AOP proxies工厂配置项接口,具体配置包括 Method Interceptors,Advice,Advisors和其他接口
ProxyCreatorSupport:proxy工厂的基类,提供了便利的方法来配置AopProxyFactory
属性:
private AopProxyFactory aopProxyFactory; //aopproxy工厂类
private List<AdvisedSupportListener> listeners = new LinkedList<>();
核心方法:
1.createAopProxy
protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();}return getAopProxyFactory().createAopProxy(this);}
实现了模板方法模式,子类通过调用createAopProxy方法来创建aopProxy
DefaultAopProxyFactory:AopProxyFactory默认实现,根据配置项创建CGLIB或者JDK Proxy
核心方法:
1.createAopProxy
描述:
1.默认情况下,全部生成JDKDynamicAopProxy
2.根据配置的isProxyTargetClass属性值:接口生成JDKDynamicAopProxy,对象生成CglibProxy
ProxyFactory:AOP Proxy的工厂类,通过简单的方式来创建AOP Proxy
属性:
TargetSource targetSource;
private List<Class<?>> interfaces = new ArrayList<>();
核心方法:
public Object getProxy() {return createAopProxy().getProxy();}public Object getProxy(@Nullable ClassLoader classLoader) {return createAopProxy().getProxy(classLoader);}
ProxyFactoryBean:基于Spring IOC模块的BeanFactory定义的Bean生成的AOP proxy工厂类
实现接口:
public class ProxyFactoryBean extends ProxyCreatorSupportimplements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware
核心方法:
1.getObject()
/*** Return a proxy. Invoked when clients obtain beans from this factory bean.* Create an instance of the AOP proxy to be returned by this factory.* The instance will be cached for a singleton, and create on each call to* {@code getObject()} for a proxy.* @return a fresh AOP proxy reflecting the current state of this factory*/@Overridepublic Object getObject() throws BeansException {initializeAdvisorChain();if (isSingleton()) {return getSingletonInstance();}else {if (this.targetName == null) {logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +"Enable prototype proxies by setting the 'targetName' property.");}return newPrototypeInstance();}}
备注:
1.根据属性值的内容(bean name)在BeanFactory获取到对应的Spring Bean,添加到advisors列表
2.根据singleton的内容,决定生成singleton bean instance还是 prototype bean instance
2.initializeAdvisorChain
/*** Create the advisor (interceptor) chain. Advisors that are sourced* from a BeanFactory will be refreshed each time a new prototype instance* is added. Interceptors added programmatically through the factory API* are unaffected by such changes.*/private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {if (this.advisorChainInitialized) {return;}if (!ObjectUtils.isEmpty(this.interceptorNames)) {if (this.beanFactory == null) {throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));}// Globals can't be last unless we specified a targetSource using the property...if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {throw new AopConfigException("Target required after globals");}// Materialize interceptor chain from bean names.for (String name : this.interceptorNames) {if (logger.isTraceEnabled()) {logger.trace("Configuring advisor or advice '" + name + "'");}if (name.endsWith(GLOBAL_SUFFIX)) {if (!(this.beanFactory instanceof ListableBeanFactory)) {throw new AopConfigException("Can only use global advisors or interceptors with a ListableBeanFactory");}addGlobalAdvisor((ListableBeanFactory) this.beanFactory,name.substring(0, name.length() - GLOBAL_SUFFIX.length()));}else {// If we get here, we need to add a named interceptor.// We must check if it's a singleton or prototype.Object advice;if (this.singleton || this.beanFactory.isSingleton(name)) {// Add the real Advisor/Advice to the chain.advice = this.beanFactory.getBean(name);}else {// It's a prototype Advice or Advisor: replace with a prototype.// Avoid unnecessary creation of prototype bean just for advisor chain initialization.advice = new PrototypePlaceholderAdvisor(name);}addAdvisorOnChainCreation(advice, name);}}}this.advisorChainInitialized = true;}
备注:遍历interceptorNames数组,通过BeanFactoryUtils.beanNamesForTypeIncludingAncestors或者 BeanFactory.getBean方法 来获取 advisor和Interceptor bean instance,并添加到Advisors列表
3.getSingletonInstance和newPrototypeInstance
/*** Return the singleton instance of this class's proxy object,* lazily creating it if it hasn't been created already.* @return the shared singleton proxy*/private synchronized Object getSingletonInstance() {if (this.singletonInstance == null) {this.targetSource = freshTargetSource();if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {// Rely on AOP infrastructure to tell us what interfaces to proxy.Class<?> targetClass = getTargetClass();if (targetClass == null) {throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");}setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));}// Initialize the shared singleton instance.super.setFrozen(this.freezeProxy);this.singletonInstance = getProxy(createAopProxy());}return this.singletonInstance;}
/*** Create a new prototype instance of this class's created proxy object,* backed by an independent AdvisedSupport configuration.* @return a totally independent proxy, whose advice we may manipulate in isolation*/private synchronized Object newPrototypeInstance() {// In the case of a prototype, we need to give the proxy// an independent instance of the configuration.// In this case, no proxy will have an instance of this object's configuration,// but will have an independent copy.if (logger.isTraceEnabled()) {logger.trace("Creating copy of prototype ProxyFactoryBean config: " + this);}ProxyCreatorSupport copy = new ProxyCreatorSupport(getAopProxyFactory());// The copy needs a fresh advisor chain, and a fresh TargetSource.TargetSource targetSource = freshTargetSource();copy.copyConfigurationFrom(this, targetSource, freshAdvisorChain());if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {// Rely on AOP infrastructure to tell us what interfaces to proxy.Class<?> targetClass = targetSource.getTargetClass();if (targetClass != null) {copy.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));}}copy.setFrozen(this.freezeProxy);if (logger.isTraceEnabled()) {logger.trace("Using ProxyCreatorSupport copy: " + copy);}return getProxy(copy.createAopProxy());}
备注:getSingletonInstance和newPrototypeInstance区别在于SingletonInstance只会初始化一次,newPrototypeInstance每次都会重新创建
Spring-AOP模块的Advised分析相关推荐
- spring aop源码实现分析
1. 先分析Advice before执行Cglib2AopProxy的intercept方法: /*** General purpose AOP callback. Used when the ta ...
- spring aop分析(一)
一.简介 Spring Aop模块采用了代理(Proxy)机制来实现AOP功能,在运行过程中aop框架大致可以分成三个阶段:创建代理.计算拦截器链.处理调用. 在"创建代理"阶段, ...
- 【Spring】Spring AOP源码分析-导读(一)
文章目录 1.简介 2.AOP 原理 3.AOP 术语及相应的实现 3.1 连接点 - Joinpoint 3.2 切点 - Pointcut 3.3 通知 - Advice 3.4 切面 - Asp ...
- Spring原理学习系列之三:Spring AOP原理(从源码层面分析)-------上部
引言 本文是Spring原理分析的第三篇博文,主要阐述Spring AOP相关概念,同时从源码层面分析AOP实现原理.对于AOP原理的理解有利于加深对Spring框架的深入理解.同时我也希望可以探究S ...
- 深入聊一聊 Spring AOP 实现机制
点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 本文转载于公众号:吉姆餐厅ak 概述 AOP(Aspect-Oriented Programmin ...
- Spring IOC 容器源码分析系列文章导读
1. 简介 前一段时间,我学习了 Spring IOC 容器方面的源码,并写了数篇文章对此进行讲解.在写完 Spring IOC 容器源码分析系列文章中的最后一篇后,没敢懈怠,趁热打铁,花了3天时间阅 ...
- Spring学习总结(9)——Spring AOP总结
spring IOC和AOP是Spring框架的两大核心基石,本文将对Spring AOP做一个系统的总结. 什么是AOP AOP(Aspect-Oriented Programming,面向切面编程 ...
- 深入聊一聊 Spring AOP 实现机制!
作者 | 张书康 责编 | 郭 芮 AOP(Aspect-Oriented Programming,即面向切面编程.Spring Aop 在 Spring框架中的地位举足轻重,主要用于实现事务.缓 ...
- AOP的实现原理 —— 静态代理 和 动态代理( Spring AOP)
文章目录 一.AOP是什么? 二.静态代理 -- AspectJ 2.1.举例说明 三. 动态代理 3.1.JDK 动态代理 3.1.1. 核心类: 3.1.2. 示例1--JDK动态代理 3.2.C ...
- spring AOP策略模式使用
1.策略模式 The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them inte ...
最新文章
- 远程办公时,有哪些提高沟通效率的技巧?
- 安装Ubuntu 14.04后要做的5件事情
- 2020-12-03 The Geometry of Rotations and Rigid-Body Motions (刚体运动和旋转的几何表示,罗德里格参数)
- tomcat的诡异的端口占用问题
- D/A转换器(华师)
- 中国联通辟谣“不支持华为”:恶意诽谤 将通过法律手段维护权益
- 将日期变为中文星期几
- php怎么取json数组元素个数,json,数组_取出json数据中的某一项组成一个数组?,json,数组,php - phpStudy...
- 布朗运动、伊藤引理、BS公式(后篇)
- 微信小程序查询数据库总条数
- 商标注册后的注意事项
- HashMap的put过程
- 在padavan运行wifidog
- 炼数成金《数据分析与SAS》课程
- Android 应用市场链接上传地址
- 2020快手前端暑期实习面经
- maven、gradle 设置MANIFEST.MF配置
- html如何删除网页边框,如何从HTML表中完全删除边框
- 治疗狗狗常见疾病药品备忘
- Codewars刷题升级 (Python)5Kyu Pete, the baker 皮特,面包师