NOTE
2.3 How AnnotationAwareAspectJAutoProxyCreator Creates Proxy Objects
Trace to postProcessBeforeInstantiation, determine whether a proxy is needed, wrap the Bean with advisors, and create JDK/CGLIB proxies
This is a historical learning note and may contain outdated or incomplete understanding.
1. Trace the Call Stack to postProcessBeforeInstantiation
Continue letting the breakpoints run and observe the creation of the Calc instance. The breakpoints mainly stop in three places:
- org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation (before Calc is instantiated)
- com.example.test.aop.AopConfig#calc (create Calc)
- org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization (after Calc is instantiated and initialized)
2. Determine Whether a Proxy Object Needs to Be Created
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
// Determine whether the current Bean is in advisedBeans (enhanced Beans).
if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// Determine whether the current Bean is one of Advice, Pointcut, Advisor, or AopInfrastructureBean,
// or whether it is an aspect (annotated with @Aspect),
// or whether it should be skipped:
// org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#shouldSkip
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
this.targetSourcedBeans.add(beanName);
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
}
return null;
}
2.1. Cases That Do Not Need a Proxy Object
org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#shouldSkip
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// Obtain all advisors (the advice methods inside the aspect).
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// Determine whether they are AspectJPointcutAdvisor instances.
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor) {
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
return true;
}
}
}
return super.shouldSkip(beanClass, beanName);
}
3. In Other Cases, Create a Proxy Object for the Bean
AbstractAutoProxyCreator#postProcessAfterInitialization
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// If there is a proxy class, use the proxy class to wrap it.
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
3.1. Wrap with Advisors
AbstractAutoProxyCreator#wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && 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;
}
// If there are advisors, create a proxy class.
// Obtain all proxy/advisor classes that can be applied to the current Bean.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// Create the proxy class.
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;
}
3.1.1. Find Suitable Advisors
AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// Obtain all advisors.
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// Filter out the advisors that can be applied.
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// Sort them.
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
3.1.2. Use the Advisors to Create a Proxy Object
AbstractAutoProxyCreator#createProxy
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// Put all advisors into ProxyFactory.
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// Use ProxyFactory to create the proxy class.
return proxyFactory.getProxy(getProxyClassLoader());
}
ProxyFactory#getProxy(java.lang.ClassLoader)
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
3.1.2.1. Create the Proxy Object with JDK or CGLIB Depending on the Situation
DefaultAopProxyFactory#createAopProxy
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)) {
return new JdkDynamicAopProxy(config);
}
// CGLIB proxy.
return new ObjenesisCglibAopProxy(config);
}
else {
// JDK dynamic proxy.
return new JdkDynamicAopProxy(config);
}
}
4. From Then On, the Calc Obtained from the Container Is the Proxy Class

Discussion
Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub