define

AOP means aspect oriented programming. It is a technology that realizes unified maintenance of program functions through precompilation and run-time dynamic proxy. It is a complement to OOP OOP programming. It is a hot technology in software development, and Spring AOP is one of the core features of the Spring framework (along with IOC)

Why was AOP introduced

  • Separate functional and non-functional requirements
  • Focus on one concern
  • Less intrusive, enhanced code readability and maintainability

AOP application scenarios

Permission control, cache control, transaction control, distributed tracing, exception handling, etc

For example, in a background management system, every time an element is modified, it needs to verify whether the operator has the operation permission. In traditional OOP, we need to write a base class, declare the authentication method, and call super.checkpriv () in the subclass. To return the result. If there are many services, each of which needs to inherit from BaseService, this can lead to over-coupling and code redundancy. AOP, on the other hand, can weave methods that require permission validation directly into a single aspect class. Just like a rental woman, all she cares about is signing contracts with users and collecting rent. If every user comes, she will show houses and negotiate prices. It was clearly not for her. So intermediaries emerge, this kind of repetitive, non-core stuff, directly to intermediaries. She can focus on signing contracts and collecting rent.

@Component
class Landlady1 {
    public void service(a) {
        // Only the core business functions are implemented
        System.out.println("Sign a contract");
        System.out.println("Rent"); }}@Component
class Landlady2 {
    public void service(a) {
        // Only the core business functions are implemented
        System.out.println("Sign a contract");
        System.out.println("Rent"); }}@Aspect
@Component
class Intermediary {

    @Pointcut("execution(* com.example.*.service())")
    public void logPointCut(a) {}@Before("logPointCut()")
    public void before(a){
        // Repetitive and non-core things
        System.out.println("Show the house to the tenant.");
        System.out.println("Negotiating the price"); }}Copy the code

The registration process

AopAutoConfiguration

AopAutoConfiguration This configuration class mainly configures the proxy type of AOP. By default, spring.aop.auto=true. When spring.aop.auto=true is true, Spring turns on AOP functionality by default by adding @enableAspectJAutoProxy to the configuration class. There are three strategies for AOP proxies after springboot2.0:

  • JDK dynamic proxy: effective when Spring.aop.proxy-target-class =false, the AspectJweaver dependency is introduced
  • Cglib proxy: effective when Spring.aop.proxy-target-class =true, with the aspectJweaver dependency introduced
  • Base proxy: when spring.aop.proxy-target-class=true, applies only to advisors within the framework if there is no AspectJweaver dependency
/ * * * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
 * Auto-configuration} for Spring's AOP support. Equivalent to enabling
 * {@link EnableAspectJAutoProxy @EnableAspectJAutoProxy} in your configuration.
 * <p>
 * The configuration will not be activated if {@literal spring.aop.auto=false}. The
 * {@literal proxyTargetClass} attribute will be {@literal true}, by default, but can be
 * overridden by specifying {@literal spring.aop.proxy-target-class=false}.
 *
 * @author Dave Syer
 * @author Josh Long
 * @since 1.0.0
 * @see EnableAspectJAutoProxy
 */
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

    // Since the default value of this annotation is true, I can't omit all of these
    @Configuration(proxyBeanMethods = false) 
	@ConditionalOnClass(Advice.class)
	static class AspectJAutoProxyingConfiguration {

		@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = false)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
		static class JdkDynamicAutoProxyConfiguration {}@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = true)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
		static class CglibAutoProxyConfiguration {}}@Configuration(proxyBeanMethods = false)
	@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
	@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
	static class ClassProxyingConfiguration {

		ClassProxyingConfiguration(BeanFactory beanFactory) {
			if (beanFactory instanceofBeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry); AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); }}}}Copy the code

@EnableAspectJAutoProxy

Can be seen from the code @ EnableAspectJAutoProxy AspectJAutoProxyRegister is introduced. The class object, AspectJAutoProxyRegister to container to register a AnnotationAwareAspectJAutoProxyCreator:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class) / / introduce AspectJAutoProxyRegister. Class object
public @interface EnableAspectJAutoProxy {
 
	// The Java interface is used to create the proxy by default. When true, the CGlib class based proxy is used
	boolean proxyTargetClass(a) default false;
 
	// Whether to expose the proxy object through an AOP framework that AopContext can access.
	boolean exposeProxy(a) default false;
}
Copy the code

AspectJAutoProxyRegistrar

Written comments are also very understand the function of the class, based on @ EnableAspectJAutoProxy annotations, the current registered a AnnotationAwareAspectJAutoProxyCreator BeanDefinitionRegistry.

/**
 * Registers an org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
 * AnnotationAwareAspectJAutoProxyCreator against the current BeanDefinitionRegistry
 * as appropriate based on a given @EnableAspectJAutoProxy annotation.
 */
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    // The following code determines whether to adopt CGlib and expose the proxy object via AOP
    / / slightly in the province
}
Copy the code

Then see AopConfigUtils directly, registerAspectJAnnotationAutoProxyCreatorIfNecessary this method, This method is the last call to registerOrEscalateApcAsRequired.

@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired( Class<? > cls, BeanDefinitionRegistry registry,@Nullable Object source) {

    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { // If Registry already contains the target bean
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        if(! cls.getName().equals(apcDefinition.getBeanClassName())) {int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            if(currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); }}return null;
    }

    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    // Otherwise register beanDefinition in Registry with the name AUTO_PROXY_CREATOR_BEAN_NAME
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}
Copy the code

AnnotationAwareAspectJAutoProxyCreator proxy objects of target object to create, in the process of creating a proxy object will create a proxy factory first, access to all the enhancer (notification method), the intensifier and target class injection agent factory, again with the factory to create objects; The proxy object executes the target method, obtains the interceptor chain of the target method, and uses the chain mechanism of the interceptor to enter each interceptor in turn for execution.