Spring 5.x 源码之旅四十七AOP代理细节二createProxy

创建代理

上篇讲了先获取匹配的通知器,其实也叫做拦截器,准备代理,这篇我们就看看是什么做的。
在这里插入图片描述

AbstractAutoProxyCreator的createProxy创建代理

进行代理工厂的创建,然后判断是否需要设置proxyTargetClass,以便于后面决定是不是要进行JDK动态代理还是CGLIB的动态代理,然后把通知器advisors包装下,加入到代理工厂,获取代理对象。

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {
		//给bean定义设置暴露属性
		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}
		// 创建代理工厂
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);//复制配置信息
		// proxyTargetClass=false的话
		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {//查看是否有PRESERVE_TARGET_CLASS_ATTRIBUTE属性,有的话就要设置true
				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());
	}

AutoProxyUtils的exposeTargetClass设置属性

其实就是设置他的原来的类型。

	static void exposeTargetClass(
			ConfigurableListableBeanFactory beanFactory, @Nullable String beanName, Class<?> targetClass) {

		if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
			beanFactory.getMergedBeanDefinition(beanName).setAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE, targetClass);
		}
	}

shouldProxyTargetClass

其实就是判断他有没有PRESERVE_TARGET_CLASS_ATTRIBUTE属性,有的话就要设置ProxyTargetClass=true

	protected boolean shouldProxyTargetClass(Class<?> beanClass, @Nullable String beanName) {
		return (this.beanFactory instanceof ConfigurableListableBeanFactory &&
				AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName));
	}

	public static boolean shouldProxyTargetClass(
			ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {

		if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
			BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
			return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
		}
		return false;
	}

ProxyProcessorSupport的evaluateProxyInterfaces

判断他的接口,是不是需要设置ProxyTargetClass=true,判断他的接口不是内部的回调接口和内部语言接口,就添加接口,否则就设置ProxyTargetClass=true

protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
		Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
		boolean hasReasonableProxyInterface = false;
		for (Class<?> ifc : targetInterfaces) {
			if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
					ifc.getMethods().length > 0) {
				hasReasonableProxyInterface = true;//用接口代理,也就是JDK
				break;
			}
		}
		if (hasReasonableProxyInterface) {//有接口
			// Must allow for introductions; can't just set interfaces to the target's interfaces only.
			for (Class<?> ifc : targetInterfaces) {
				proxyFactory.addInterface(ifc);
			}
		}
		else {//没接口就设置true
			proxyFactory.setProxyTargetClass(true);
		}
	}
ProxyProcessorSupport的isConfigurationCallbackInterface

是不是内部的一些接口。

	protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
		return (InitializingBean.class == ifc || DisposableBean.class == ifc || Closeable.class == ifc ||
				AutoCloseable.class == ifc || ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
	}
ProxyProcessorSupport的isInternalLanguageInterface

是不是内部语言的一些接口。

	protected boolean isInternalLanguageInterface(Class<?> ifc) {
		return (ifc.getName().equals("groovy.lang.GroovyObject") ||
				ifc.getName().endsWith(".cglib.proxy.Factory") ||
				ifc.getName().endsWith(".bytebuddy.MockAccess"));
	}

AdvisedSupport的addInterface

添加接口:

	public void addInterface(Class<?> intf) {
		Assert.notNull(intf, "Interface must not be null");
		if (!intf.isInterface()) {
			throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
		}
		if (!this.interfaces.contains(intf)) {
			this.interfaces.add(intf);
			adviceChanged();
		}
	}
ProxyCreatorSupport的adviceChanged

添加了接口要有adviceChanged通知,不过一般我们没用到这个。

	@Override
	protected void adviceChanged() {
		super.adviceChanged();//清除缓存
		synchronized (this) {
			if (this.active) {
				for (AdvisedSupportListener listener : this.listeners) {
					listener.adviceChanged(this);
				}
			}
		}
	}

ProxyFactory的getProxy获取代理

先创建AopProxy代理,然后获取代理。

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

创建AOP代理,如果激活了,就需要有激活通知,我们也也不太用到:

	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		return getAopProxyFactory().createAopProxy(this);
	}
ProxyCreatorSupport的activate

激活通知,跟前面的添加接口的通知一样,都是给AdvisedSupportListener通知。:

	private void activate() {
		this.active = true;
		for (AdvisedSupportListener listener : this.listeners) {
			listener.activated(this);
		}
	}
DefaultAopProxyFactory的createAopProxy

这个才是真正创建代理,判断一些列条件,有自定义的接口的就会创建JDK代理,否则就是CGLIB

	@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)) {//有接口或者是proxy类型的用JDK
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);//用CGLIB
		}
		else {
			return new JdkDynamicAopProxy(config);//用JDK
		}
	}
DefaultAopProxyFactory的hasNoUserSuppliedProxyInterfaces

这个就是说如果存在一个接口,还是SpringProxy类型的,就返回true,否则就是false,我们自定义的肯定是false,如果没接口也是false

	private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
		Class<?>[] ifcs = config.getProxiedInterfaces();
		return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
	}
JdkDynamicAopProxy的getProxy

如果是JDK的动态代理,就是我们熟悉的Proxy.newProxyInstance,不过这里调用前还做了一些处理。

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);//生成代理
	}

后面我们继续来说这个处理吧。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值