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/…