Spring: Spring Aop create an agent

1. Mito

Here Insert Picture Description

2. Overview

Looking for agents, please refer to the previous article

3. preamble Overview

/**
	 * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
	 * @param bean the raw bean instance
	 * @param beanName the name of the bean
	 * @param cacheKey the cache key for metadata access
	 * @return a proxy wrapping the bean, or the raw bean instance as-is
	 *
	 * 如果需要则包装该bean,例如该bean可以被代理
	 */
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// 1、如果已经处理过或者不需要创建代理,则返回
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		// 2、创建代理
		// 2.1 根据指定的bean获取所有的适合该bean的增强
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			// 2.2 为指定bean创建代理
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		// 3、缓存
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

The second major step here is to create a proxy

4. Create a proxy

/**
	 * 为给定的bean创建代理
	 *
	 * Create an AOP proxy for the given bean.
	 * @param beanClass the class of the bean
	 * @param beanName the name of the bean
	 * @param specificInterceptors the set of interceptors that is
	 * specific to this bean (may be empty, but not null)
	 * @param targetSource the TargetSource for the proxy,
	 * already pre-configured to access the bean
	 * @return the AOP proxy for the bean
	 * @see #buildAdvisors
	 */
	protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		// 1、当前beanFactory是ConfigurableListableBeanFactory类型,则尝试暴露当前bean的target class
		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		// 2、创建ProxyFactory并配置
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		// 是否直接代理目标类以及接口
		if (!proxyFactory.isProxyTargetClass()) {
			// 确定给定bean是否应该用它的目标类而不是接口进行代理
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			// 检查给定bean类上的接口,如果合适的话,将它们应用到ProxyFactory。即添加代理接口
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		// 3、确定给定bean的advisors,包括特定的拦截器和公共拦截器,是否适配Advisor接口。
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		// 设置增强
		proxyFactory.addAdvisors(advisors);
		// 设置代理目标
		proxyFactory.setTargetSource(targetSource);
		// 定制proxyFactory(空的模板方法,可在子类中自己定制)
		customizeProxyFactory(proxyFactory);

		// 锁定proxyFactory
		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		// 4、创建代理
		return proxyFactory.getProxy(getProxyClassLoader());
	}

4.1 Creating specific process agents

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

	/**
	 * Subclasses should call this to get a new AOP proxy. They should <b>not</b>
	 * create an AOP proxy with {@code this} as an argument.
	 */
	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		return getAopProxyFactory().createAopProxy(this);
	}

We can see from the above code, create a proxy to a specific work commissioned by AopProxyFactorythe createAopProxymethod.

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		// 1、判断是否需要创建CGLIB动态代理
		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.");
			}
			// todo 这里有疑问 即
			// targetClass.isInterface()
			// Proxy.isProxyClass(targetClass)
			// 什么情况下会生效
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				// 创建jdk动态代理
				return new JdkDynamicAopProxy(config);
			}
			// 创建CGLIB动态代理
			return new ObjenesisCglibAopProxy(config);
		}
		// 2、默认创建JDK动态代理
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

Here we finally see the judgment conditions and judgment CGLIB JDK dynamic proxy, which is the interview will encounter a common problem.

Determine the need to create a dynamic proxy CGLIB

  1. config.isOptimize():Judged by CGLIBwhether the agent optimization strategy to create
    the conditions for the value of ProxyConfigthe class optimizeattribute. Whether this attribute to mark agent optimization. Start optimization usually means after the proxy object is created, enhanced modifications will not take effect, so the default value false. If exposeProxyyou set to true, even optimizeas trueit will be ignored.
  2. config.isProxyTargetClass(): Are configured proxy-target-classto true
    values in the condition ProxyConfigclass proxyTargetClassattributes. This attribute is marked directly on the target class if the proxy, rather than through the interface generation agent.
  3. hasNoUserSuppliedProxyInterfaces(config): Is there a proxy interface

Any satisfying the above three conditions will be considered open CGLIBdynamic proxy, but in this ifthere is another layer in the determination condition targetClass.isInterface() || Proxy.isProxyClass(targetClass), i.e., if the target itself is an interface class, the target class, or by Proxy.newProxyInstance()或Proxy.getProxyClass()generating, still using the jdkdynamic proxies .

4.2 dynamic proxy get CGLIB

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
		}

		try {
			Class<?> rootClass = this.advised.getTargetClass();
			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

			Class<?> proxySuperClass = rootClass;
			if (ClassUtils.isCglibProxyClass(rootClass)) {
				proxySuperClass = rootClass.getSuperclass();
				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
				for (Class<?> additionalInterface : additionalInterfaces) {
					this.advised.addInterface(additionalInterface);
				}
			}

			// Validate the class, writing log messages as necessary.
			validateClassIfNecessary(proxySuperClass, classLoader);

			// Configure CGLIB Enhancer...
			// 新建并配置Enhancer
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
			enhancer.setSuperclass(proxySuperClass);
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			// fixedInterceptorMap only populated at this point, after getCallbacks call above
			enhancer.setCallbackFilter(new ProxyCallbackFilter(
					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);

			// Generate the proxy class and create a proxy instance.
			// 生成代理类并创建代理实例
			return createProxyClassAndInstance(enhancer, callbacks);
		}
		catch (CodeGenerationException | IllegalArgumentException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
					": Common causes of this problem include using a final class or a non-visible class",
					ex);
		}
		catch (Throwable ex) {
			// TargetSource.getTarget() failed
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}

Then look at Spring: Spring Aop CGLIB dynamic proxy invocation

4.3 get JDK dynamic proxies

@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		// 确定用于给定AOP配置的代理的完整接口集。
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		// 判断被代理接口有没有重写equals和hashCode方法
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		// 为接口创建代理
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

Then look at Spring: Spring Aop JDK dynamic proxy invocation

Released 1017 original articles · won praise 435 · Views 1.26 million +

Guess you like

Origin blog.csdn.net/qq_21383435/article/details/104018140