首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringAop源码分析(基于注解)三:创建代理对象

SpringAop源码分析(基于注解)三:创建代理对象

作者头像
炳臣
发布2019-10-24 19:03:03
4070
发布2019-10-24 19:03:03
举报
文章被收录于专栏:一块自留地一块自留地

我们先回到Bean初始化之后,调用BeanPostProcessor后置处理器的地方。

//AbstractAutoProxyCreator.java

//在Bean初始化之后回调
@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)) {
			// 没有,为 bean 生成代理对象
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	return bean;
}

wrapIfNecessary代码:

//AbstractAutoProxyCreator.java

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
		return bean;
	}
	if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
		return bean;
	}

	/*
	 * 如果是基础设施类(Pointcut、Advice、Advisor 等接口的实现类),或是应该跳过的类,
	 * 则不应该生成代理,此时直接返回 bean
	 */
	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

	// Create proxy if we have advice.
<1>	// 返回匹配当前 bean 的所有的通知器  advisor、advice、interceptor
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	if (specificInterceptors != DO_NOT_PROXY) {
		this.advisedBeans.put(cacheKey, Boolean.TRUE);
		// 核心!创建代理对象
<2>		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;
}

上篇文章我们主要分析的是<1>处代码,现在有了合适的通知器,我们要为当前Bean创建代理对象,把通知器(Advisor)所持有的通知(Advice)织入到 bean 的某些方法前后。

看代码:

//AbstractAutoProxyCreator.java

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);

	//proxyTargetClass是 @EnableAspectJAutoProxy 的属性之一
	//true -> 强制使用CGLIB代理
	if (!proxyFactory.isProxyTargetClass()) {
		//false
		if (shouldProxyTargetClass(beanClass, beanName)) {
			proxyFactory.setProxyTargetClass(true);
		}
		else {
			//检测 beanClass 是否实现了接口,若未实现,则将
			//proxyFactory 的成员变量 proxyTargetClass 设为 true
			evaluateProxyInterfaces(beanClass, proxyFactory);
		}
	}
    
        //封装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
  • 判断使用JDK还是CGLIB
  • 封装ProxyFactory
  • 创建并获取代理对象

这里的 isProxyTargetClass() 其实就是我们前面用的注解@EnableAspectJAutoProxy的属性之一,当其为true时,强制使用CGLIB代理。

下面我们接着看创建代理的代码:

//ProxyFactory.java

public Object getProxy(@Nullable ClassLoader classLoader) {
	return createAopProxy().getProxy(classLoader);
}

这段方法有两个方法调用:

  • createAopProxy() 创建 AopProxy 实现类对象
  • getProxy(classLoader) 创建代理对象

我们先来看下createAopProxy():

//DefaultAopProxyFactory.java

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	//if中的3个条件
	//1、 config.isOptimize() - 是否需要优化
	//2、 config.isProxyTargetClass() - 检测 proxyTargetClass 的值
	//3、 hasNoUserSuppliedProxyInterfaces(config) - 目标 bean 是否实现了接口
	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)) {
			//创建JdkDynamicAopProxy
			return new JdkDynamicAopProxy(config);
		}
		//创建CglibAopProxy
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		//创建JdkDynamicAopProxy
		return new JdkDynamicAopProxy(config);
	}
	}

最终调用的是DefaultAopProxyFactory#createAopProxy(...)方法,通过这个方法创建AopProxy 的实现类,如: JdkDynamicAopProxy,然后根据这个实现类再创建代理对象。

我们以JdkDynamicAopProxy为例,看下getProxy(classLoader):

//JdkDynamicAopProxy.java

public Object getProxy() {
    return getProxy(ClassUtils.getDefaultClassLoader());
}

public Object getProxy(ClassLoader classLoader) {
    if (logger.isDebugEnabled()) {
        logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
    }
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    
    // 调用 newProxyInstance 创建代理对象
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

直接看代码最后一行,最终调用 Proxy.newProxyInstance 方法创建代理对象。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年10月21日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云顾问
云顾问(Tencent Cloud Smart Advisor)是一款提供可视化云架构IDE和多个ITOM领域垂直应用的云上治理平台,以“一个平台,多个应用”为产品理念,依托腾讯云海量运维专家经验,助您打造卓越架构,实现便捷、灵活的一站式云上治理。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档