AOP实现之代理bean创建过程(三)

上篇文章中已经讲解完毕spring是怎样来解析我们xml中的aop配置,同时也讲到了在解析过程中,它将会为我们创建几个必要的bean对像,接下来我们就讲解spring是如何来创建我们的代理对象的;


在讲IOC的实现原理时,我们就说过,只有我们在第一次使用某个bean的时候,beanFactory才会为我们来创建bean对象(除非设置了lazy-init为false),代理bean的创建和普通bean的创建过程完全一样,这里不多说,可以去看前面的文章;我们直接将断点打到AbstractAutowireCapableBeanFactory.initializeBean()方法中,这个方法是在bean创建完毕,对它进行一些后续处理时得到调用(后续处理包括调用前处理器,调用配置的init-method方法,调用后处理器) 。 如果你忘记了的话,去看看前面IOC原理解析的文章,那里有详细的解释;


瞧瞧下方两个截图:



我们看到,在上篇文章中说到的AspectJAwareAdvisorAutoProxyCreator类在这里将得到调用机会,同时,此时我们的bean还是AopTargetInterfaceImpl类,这是没有任何问题的;


我们跳进后处理方法中去看看;

@Override
public Object postProcessAfterInitialization(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;
}

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	// 拿到先前spring为我们创建好的AspectJPointcutAdvisor通知器,
	//关于通知器中包含的内容,和我们上篇文章说的一样,可以看下截图
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	if (specificInterceptors != DO_NOT_PROXY) {
		this.advisedBeans.put(cacheKey, Boolean.TRUE);
		//去创建一个代理bean
		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;
}



我们继续去看创建代理bean的方法;


//创建代理bean的方法
protected Object createProxy(
		Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
	//创建一个代理工厂
	ProxyFactory proxyFactory = new ProxyFactory();
	proxyFactory.copyFrom(this);

	if (!proxyFactory.isProxyTargetClass()) {
		//是否直接代理这个类,这个类没有实现任何接口
		if (shouldProxyTargetClass(beanClass, beanName)) {
			proxyFactory.setProxyTargetClass(true);
		}
		else {
			//我们的bean实现了接口,将进入这里,这个方法将填充proxyFactory的interfaces属性,
			//也就是配置好代理工厂即将要代理的接口
			evaluateProxyInterfaces(beanClass, proxyFactory);
		}
	}
	
	//将specificInterceptors包装成Advisor,这里没什么好说的,specificInterceptors数组里本身装的就是Advisor的实现类
	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
	for (Advisor advisor : advisors) {
		//配置好代理工厂的通知器
		proxyFactory.addAdvisor(advisor);
	}
	
	proxyFactory.setTargetSource(targetSource);
	customizeProxyFactory(proxyFactory);

	proxyFactory.setFrozen(this.freezeProxy);
	if (advisorsPreFiltered()) {
		proxyFactory.setPreFiltered(true);
	}
	
	//======>>>重点在这里
	return proxyFactory.getProxy(getProxyClassLoader());
}

public Object getProxy(ClassLoader classLoader) {
	//先通过createAopProxy()拿到一个代理对象调用处理程序AopProxy,再交给委托对象去创建代理bean
	//AopProxy有两个实现类,CglibAopProxy以及JdkDynamicAopProxy
	return createAopProxy().getProxy(classLoader);
}

//得到代理委托对象
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	//如果bean没有实现接口,就创建一个基于Cglib库实现的CglibAopProxy
	//现在明白Spring是怎么来选择到底是使用Cglib还是JDK的proxy来创建代理了吧!就是根据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()) {
			return new JdkDynamicAopProxy(config);
		}
		return new ObjenesisCglibAopProxy(config);
	}
	//否则创建基于JDK自带的Proxy实现的JdkDynamicAopProxy
	else {
		return new JdkDynamicAopProxy(config);
	}
	}
	
//真正得到一个代理bean,这里没什么好说的,就是通过JDK自带的Proxy来实现,不明白的话可以去了解下JDK的动态代理
//至于cglib的代理创建原理,我也未做深入研究,感兴趣的话可以自己去看看源码
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);
	findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
	//创建代理bean,它的调用处理程序是this,也就是JdkDynamicAopProxy,因为JdkDynamicAopProxy实现了InvocationHandler接口
	//故此,当我们后面在调用代理bean的相关方法时,都将先执行JdkDynamicAopProxy的invoke方法,
	//而JdkDynamicAopProxy实例中已经存好了我们的Advisor通知器,为后面的方法增强做好了准备!
	return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}




现在调用堆栈一路返回,最终回到我们先前的调用后处理器代码的地方,我们看下截图:



至此,代理bean已经创建完毕,当我们通过getBean()拿到的对象已经是一个代理对象了;下篇文章我们就来讲解代理bean的调用过程中,增强方法到底是如何做到增强的;


现在,我们来总结一下一个代理bean的创建过程,最后再画一个时序图;

首先,通过AspectJAwareAdvisorAutoProxyCreator这个类的后处理方法,代理bean有了创建入口,接下来将创建一个ProxyFactory并配置好这个ProxyFactory,包括配置要代理的接口,以及一系列通知器,然后根据bean是否有实现接口来创建一个JdkDynamicApoProxy或者ObjenesisCglibAopProxy代理处理器,再通过处理器的getProxy()方法获得一个真正的代理对象,拿到代理对象后,方法一路返回最终回到调用后处理方法的地方,替换掉我们原本创建好的bean;








  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值