实验环境:spring-framework-5.0.2、jdk8、gradle4.3.1

历史文章

AOP代理对象也是在bean的实例化过程中创建的,如果不明白可以看一下bean实例化过程。如果类配置了@EnableAspectJAutoProxy注解 ,Spring则会在BeanPostProcessor.after这一步通过AnnotationAwareAspectJAutoProxyCreator这个BeanPostProcessor创建一个代理对象,替换掉了原有的bean对象返回了出去。

我们再来看一下bean创建流程

创建bean方法如下

doCreateBean方法
/**
* 真正创建bean的方法
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException { // 封装被创建的bean对象
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// TODO【重要】 这一步创建了bean实例,只是一个早期的对象,还没有填充属性值
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance(); // 获取实例化对象的类型
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
} // 调用post-processors
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
} // 向容器中缓存单例模式的bean,防止循环引用
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// TODO【重要】 向三级缓存添加bean实例 匿名内部类,防止循环引用,尽早持有对象的引用
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
} // 初始化bean实例,exposedObject在初始化完成之后返回依赖注入完成之后的bean
Object exposedObject = bean;
try {
// TODO 【重要】 bean属性依赖注入,并且将bean定义中配置的属性值赋值给实例对象
populateBean(beanName, mbd, instanceWrapper); // TODO 【重要】开始初始化bean对象(含AOP)
// 调用Aware接口方法 -> 调用BeanPostProcessor.before方法 -> 调用init-method方法 -> 调用BeanPostProcessor.after方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
} if (earlySingletonExposure) {
// 获取指定名称的已注册的单例bean
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
// 根据名称获取已注册的bean和正在实例化的bean是同一个
if (exposedObject == bean) {
// 当前实例化的bean初始完成
exposedObject = earlySingletonReference;
}
// 当前bean依赖其他bean,且当发送循环引用时,不允许创建新的实例对象
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
// 获取当前bean所依赖的其他bean
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
// 对依赖bean进行类型检查
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
} // 注册完成依赖注入的bean
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
} return exposedObject;
} /**
* 初始化容器创建的bean实例对象,为其添加BeanPostProcessor后置处理器
* 调用Aware接口方法 -> 调用BeanPostProcessor.before方法 -> 调用init-method方法 -> 调用BeanPostProcessor.after方法
*/
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// 通过JDK的安全机制验证权限
if (System.getSecurityManager() != null) {
// 实现PrivilegedAction接口的匿名内部类
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 为bean实例对象包装相关属性,如名称、类加载器、所属容器等
invokeAwareMethods(beanName, bean);
} Object wrappedBean = bean;
// 调用BeanPostProcessor后置处理器的回调方法,在bean实例初始化前做一些处理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
} try {
// 调用init方法 (@PostConstruct标注的init方法)
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 调用BeanPostProcessor后置处理器的回调方法,在bean实例初始化后做一些处理(AOP会在这一步实现代理对象)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
} return wrappedBean;
} /**
* 后置处理器:在bean初始化之后,init方法之后调用
*/
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
// 依次执行BeanPostProcessor的postProcessAfterInitialization实现方法
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

我们看的有个applyBeanPostProcessorsAfterInitialization方法,会循环调用所有的BeanPostProcessor对当前bean做增强,如果这个bean配置了AOP代理的话,则会通AnnotationAwareAspectJAutoProxyCreator.postProcessAfterInitialization方法创建一个代理对象。我们来看一下其父类AbstractAutoProxyCreator的实现逻辑。

AbstractAutoProxyCreator#postProcessAfterInitialization方法
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// 如果有需要则做一下包装
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
} /**
* 如果有需要则包装一下当前bean
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 判断是否应该代理这个bean
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
/**
* 判断是否是一些InfrastructureClass或者是否应该跳过这个bean
* InfrastructureClass是指Advice、PointCut、Advisor等接口的实现类
*/
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
} // Create proxy if we have advice.
// 获取这个bean的通知
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE); // 创建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
} /**
* 创建代理对象
*/
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
} ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this); if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
} Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
} // 这一步创建了一个代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}

我们看的是通过 proxyFactory.getProxy来创建的代理对象,调用getProxy就会返回CglibAopProxy或JdkDynamicAopProxy代理对象。

ProxyFactory#getProxy方法
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}

那么是怎么决定返回的是CglibAopProxy还是JdkDynamicAopProxy代理对象呢?是通过createAopProxy方法来决定的。

DefaultAopProxyFactory#createAopProxy方法
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
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);
}
}

到此,一个代理对象就创建了出来。

Spring源码-AOP部分-Spring是如何对bean实现AOP代理的的更多相关文章

  1. Spring源码-IOC部分-Spring是如何解决Bean循环依赖的【6】

    实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...

  2. Spring源码剖析4:其余方式获取Bean的过程分析

    原型Bean加载过程 之前的文章,分析了非懒加载的单例Bean整个加载过程,除了非懒加载的单例Bean之外,Spring中还有一种Bean就是原型(Prototype)的Bean,看一下定义方式: 1 ...

  3. Spring源码-IOC部分-自定义IOC容器及Bean解析注册【4】

    实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...

  4. 框架源码系列六:Spring源码学习之Spring IOC源码学习

    Spring 源码学习过程: 一.搞明白IOC能做什么,是怎么做的  1. 搞明白IOC能做什么? IOC是用为用户创建.管理实例对象的.用户需要实例对象时只需要向IOC容器获取就行了,不用自己去创建 ...

  5. Spring源码分析(十八)创建bean

    本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.创建bean的实例 1. autowireConstructor 2 ...

  6. spring源码深度解析—Spring的整体架构和环境搭建

    概述 Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用.Spring是于2003 年兴起的一个轻量级的Java 开发框 ...

  7. Spring源码分析:Spring IOC容器初始化

    概述: Spring 对于Java 开发来说,以及算得上非常基础并且核心的框架了,在有一定开发经验后,阅读源码能更好的提高我们的编码能力并且让我们对其更加理解.俗话说知己知彼,百战不殆.当你对Spri ...

  8. Spring源码分析(十四)从bean的实例中获取对象

    摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 在getBean方法中,getObjectForBeanlnstance ...

  9. spring源码学习(三)--spring循环引用源码学习

    在spring中,是支持单实例bean的循环引用(循环依赖)的,循环依赖,简单而言,就是A类中注入了B类,B类中注入了A类,首先贴出我的代码示例 @Component public class Add ...

  10. spring源码分析之玩转ioc:bean初始化和依赖注入(一)

    最近赶项目,天天加班到十一二点,终于把文档和代码都整完了,接上继续整. 上一篇聊了beanProcess的注册以及对bean的自定义修改和添加,也标志着创建bean的准备工作都做好了,接下来就是开大招 ...

随机推荐

  1. Anniversary party(hdu1520)

    Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  2. 1025 - The Specials Menu

    1025 - The Specials Menu    PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 ...

  3. 终于做了一把MySQL调参boy

    本文通过笔者经历的一个真实案例来介绍一个MySQL中的重要参数innodb_buffer_pool_size,希望能给大家带来些许收获,当遇到类似性能问题时可以多一种思考方式. 图片拍摄于大唐不夜城 ...

  4. Order Statistic

    目录 The Order Statistic 引理1 的一些基本性质 顺序统计量的分布 顺序统计量的条件分布 特殊分布的特殊性质 Order Statistic The Order Statistic ...

  5. JavaWeb项目作业 Market商品管理系统

    目录 一.语言和环境 二.实现功能 三.数据库设计 四.实现代码 一.语言和环境 实现语言:Java语言. 环境要求:MyEclipse(Eclipse)+MySQL. 实现方式:JBDC.jsp/s ...

  6. JavaScript交互式网页设计 • 【第7章 jQuery操作 DOM】

    全部章节   >>>> 本章目录 7.1 DOM 对象和 jQuery 对象 7.1.1 DOM 对象 7.1.2 jQuery 对象 7.1.3 jQuery 对象和 DOM ...

  7. Kerberos认证过程学习理解

    概念: Kerberos服务器:AS认证服务器,TGS服务授权服务器 Client 客户端,代表使用应用的用户 AppServer 服务端,应用提供各种服务的服务器 Client在Kerberos注册 ...

  8. Kerberos打开debug日志

    在JVM的启动参数中加入如下配置,打开kerberos的debug开关: -Dsun.security.krb5.debug=true JVM启动后,kerberos的相关日志会打印到控制台中, 因为 ...

  9. java POJO中 Integer 和 int 的不同,用int还是用Integer

    https://www.jianshu.com/p/ff535284916f [int和Integer的区别] int是java提供的8种原始类型之一,java为每个原始类型提供了封装类,Intege ...

  10. Nginx 加载conf.d (内文件***.conf)

    include /usr/local/nginx/conf/conf.d/*.conf;