In SpringAop source code analysis (based on annotations) 2: filter notifier, we analyzed the creation and filtering process of advice in AOP. In this chapter, we take a look at how AOP creates proxy objects.

Let’s go back to where the BeanPostProcessor was called after the Bean was initialized.

//AbstractAutoProxyCreator.java

// Callback after Bean initialization
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
	if(bean ! =null) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		// Check if there is any in the cache
		if (!this.earlyProxyReferences.contains(cacheKey)) {
			// No, generate proxy object for bean
			returnwrapIfNecessary(bean, beanName, cacheKey); }}return bean;
}
Copy the code

WrapIfNecessary code:

//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;
	}

	/* * If it is an infrastructure class (a class that implements interfaces such as Pointcut, Advice, Advisor, etc.) or a class that should be skipped, the proxy should not be generated and bean */ should be returned
	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

	// Create proxy if we have advice.
<1>	// Returns all advisors, advice, and interceptor that match the current bean
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	if(specificInterceptors ! = DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);
		/ / core! Creating a proxy object
<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;
}
Copy the code

In the previous article we focused on code at <1>. Now that we have the appropriate notifier, we will create a proxy object for the current Bean to weave the Advice held by the notifier Advisor around some of the Bean’s methods.

Look at the code:

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

	// Create a proxy factory
	ProxyFactory proxyFactory = new ProxyFactory();
	proxyFactory.copyFrom(this);

	//proxyTargetClass is one of the attributes of @enableAspectJAutoProxy
	//true -> Force the CGLIB proxy
	if(! proxyFactory.isProxyTargetClass()) {//false
		if (shouldProxyTargetClass(beanClass, beanName)) {
			proxyFactory.setProxyTargetClass(true);
		}
		else {
			// Check whether the beanClass implements the interface
			// Set the proxyFactory member variable proxyTargetClass to trueevaluateProxyInterfaces(beanClass, proxyFactory); }}/ / encapsulation proxyFactory
	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
	proxyFactory.addAdvisors(advisors);
	proxyFactory.setTargetSource(targetSource);
	customizeProxyFactory(proxyFactory);

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

	// Create and get the proxy object
	return proxyFactory.getProxy(getProxyClassLoader());
	}
Copy the code

Here we focus on the core logic:

  • Create the ProxyFactory ProxyFactory
  • Determine whether to use JDK or CGLIB
  • Encapsulation ProxyFactory
  • Create and get the proxy object

The isProxyTargetClass() is actually one of the attributes of the @enableAspectJAutoProxy annotation we used earlier. When it is true, the CGLIB proxy is enforced.

Let’s move on to the code that creates the proxy:

//ProxyFactory.java

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

This method section has two method calls:

  • CreateAopProxy () creates the AopProxy implementation object
  • GetProxy (classLoader) Creates a proxy object

Let’s start with createAopProxy() :

//DefaultAopProxyFactory.java

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	// Three conditions in if
	//1, config.isoptimize () - Whether optimization is required
	/ / 2, config. IsProxyTargetClass () - testing proxyTargetClass values
	/ / 3, hasNoUserSuppliedProxyInterfaces (config) - whether target bean implements the interface
	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 the target class is an interface | | or the target class is a proxy class
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			/ / create JdkDynamicAopProxy
			return new JdkDynamicAopProxy(config);
		}
		/ / create CglibAopProxy
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		/ / create JdkDynamicAopProxy
		return newJdkDynamicAopProxy(config); }}Copy the code

DefaultAopProxyFactory#createAopProxy(…) Method to create an implementation class for AopProxy, such as JdkDynamicAopProxy, and then create a proxy object based on the implementation class.

Let’s take JdkDynamicAopProxy as an example and look at getProxy(classLoader):

//JdkDynamicAopProxy.java

public Object getProxy(a) {
    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);
    
    Call newProxyInstance to create the proxy object
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
Copy the code

Go straight to the last line of the code and finally call the proxy.newProxyInstance method to create the Proxy object.

Reference: www.tianxiaobo.com/2018/06/20/…