A list,

AOP is implemented in Spring, automatically incorporated into the IOC container management, using annotations and dynamic proxy technology, to achieve the aspect function.

Second, source code analysis

AopAutoConfiguration

@configuration // Condition Configuration class. If the condition is met, Just open the AOP functionality @ ConditionalOnClass ({EnableAspectJAutoProxy. Class, Aspect. Class, Advice. The class, AnnotatedElement.class}) @ConditionalOnProperty( prefix = "spring.aop", name = {"auto"}, havingValue = "true", matchIfMissing = true ) public class AopAutoConfiguration { public AopAutoConfiguration() { } @Configuration @EnableAspectJAutoProxy( proxyTargetClass = true ) @ConditionalOnProperty( prefix = "spring.aop", name = {"proxy-target-class"}, havingValue = "true", matchIfMissing = true ) public static class CglibAutoProxyConfiguration { public CglibAutoProxyConfiguration() { } } @Configuration @EnableAspectJAutoProxy( proxyTargetClass = false ) @ConditionalOnProperty( prefix = "spring.aop", name = {"proxy-target-class"}, havingValue = "false", matchIfMissing = false ) public static class JdkDynamicAutoProxyConfiguration { public JdkDynamicAutoProxyConfiguration() { } } }Copy the code
  • AopAutoConfiguration is an automatic assembly class provided by SpringBoot for AOP.

  • Open automatically SpringBoot Aop proxy mechanism, the default CglibAutoProxyConfiguration configuration. If you need interface-based dynamic proxies (JDK interface-based dynamic proxies), you need to set the spring.aop.proxy-target-class property to false.

EnableAspectJAutoProxy

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy { /** * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed * to standard Java interface-based proxies. The default is {@code false}. */ boolean proxyTargetClass() default false; /** * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal} * for retrieval via the {@link org.springframework.aop.framework.AopContext} class. * Off by default, * @since 4.3.1 */ Boolean exposeProxy() default false; }Copy the code

Annotations turn on the proxy mechanism and tell the Spring container to support annotated aspects.

  • ProxyTargetClass specifies whether a proxy is created using CGLIB to implement the target object of the interface. The default value is false, using JDK to create a proxy for the interface object.

  • ExposeProxy flags whether the proxy object should be exposed as ThreadLocal by the AOP framework via AopContext. This property is useful when a proxy object needs to call another proxy method of its own. The default is false to avoid unnecessary interception.

AspectJAutoProxyRegistrar

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { /** * Register, escalate, and configure the AspectJ auto proxy creator based on the value * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing * {@code @Configuration} class. */ @Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); if (enableAspectJAutoProxy ! = null) { if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); }}}}Copy the code

This class registered AspectJAnnotationAutoProxyCreator and enableAspectJAutoProxy enableAspectJAutoProxy annotation information, the default forced open class agent.

AopConfigUtils

public abstract class AopConfigUtils { ..... @Nullable public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) { return registerAspectJAutoProxyCreatorIfNecessary(registry, (Object)null); } @Nullable public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) { return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); } @Nullable private static BeanDefinition registerOrEscalateApcAsRequired(Class<? > cls, BeanDefinitionRegistry registry, @Nullable Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) { BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator"); if (! cls.getName().equals(apcDefinition.getBeanClassName())) { int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } else {/ / registered AnnotationAwareAspectJAutoProxyCreator RootBeanDefinition beanDefinition = new RootBeanDefinition (CLS); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", -2147483648); beanDefinition.setRole(2); registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition); return beanDefinition; }}}Copy the code

At the start of the AutoProxyCreator class does not exist, RootBeanDefinition initialization AnnotationAwareAspectJAutoProxyCreator class, registered to the IOC container.

AnnotationAwareAspectJAutoProxyCreator

Inheritance relationships

AnnotationAwareAspectJAutoProxyCreator->AspectJAwareAdvisorAutoProxyCreator->AbstractAdvisorAutoProxyCreator->AbstractAu toProxyCreator

Post-processing of the Bean life cycle

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware{ ...... public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean ! = null) { Object cacheKey = this.getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) ! = bean) { return this.wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } else if (! this.isInfrastructureClass(bean.getClass()) && ! this.shouldSkip(bean.getClass(), beanName)) { Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null); // Get all notifications for pointcuts to be woven into the beanName target object if (specificInterceptors! = DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } else { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } } else { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }}... }Copy the code

Important: Create the proxy class

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); } ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); if (! proxyFactory.isProxyTargetClass()) { if (this.shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { this.evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); proxyFactory.setTargetSource(targetSource); this.customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (this.advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(this.getProxyClassLoader()); }Copy the code

DefaultAopProxyFactory

Inheritance relationships

DefaultAopProxyFactory->AopProxyFactory

Create a proxy factory

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (! config.isOptimize() && ! config.isProxyTargetClass() && ! this.hasNoUserSuppliedProxyInterfaces(config)) { return new JdkDynamicAopProxy(config); } else { 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."); } else { return (AopProxy)(! targetClass.isInterface() && ! Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config)); }}}}Copy the code

The class interface uses the JDK proxy, and the classes use the Cglib proxy.

AopProxy

Inheritance relationships

JdkDynamicAopProxy->AopProxy

ObjenesisCglibAopProxy->CglibAopProxy->AopProxy

Get a proxy object

public interface AopProxy {
   Object getProxy();

   Object getProxy(@Nullable ClassLoader var1);
}


 public Object getProxy() {
    return this.getProxy(ClassUtils.getDefaultClassLoader());
}
Copy the code

Third, summary

1.AopAutoConfiguration implements automatic assembly of Aop, and can be used directly after configuring dependencies.

2.EnableAspectJAutoProxy Annotation to enable the Proxy function of AspectJ.

3. AspectJAutoProxyRegistrar realize dynamic registration AnnotationAwareAspectJAutoProxyCreator, included in the IOC container management.

4. AnnotationAwareAspectJAutoProxyCreator implementation life cycle monitoring, rear handle AspectJ cut class, find the cache all Advisors, create the proxy class object.

5.DefaultAopProxyFactory provides a proxy policy. The interface uses the JDK proxy and the class uses the Cglib proxy. By default, SpringBoot uses the Cglib agent.

6.AopProxy creates a proxy class that inserts the code in the Advisor annotated method and returns the proxy object.