Spring Advanced Topics - How the @Enable*** Annotation Works

Reprinted from: https://blog.csdn.net/qq_26525215/article/details/53524844

@EnableAspectJAutoProxy

@EnableAspectJAutoProxy annotation activates Aspect automatic proxy


1
Turn on support for AspectJ auto-proxy.

It is used when using AOP's automatic proxy. If you understand Java's dynamic proxy, it is easy to be familiar with AOP's automatic proxy.

@EnableAsync

The @EnableAsync annotation enables asynchronous method support.
I'm sure everyone is familiar with this. Asynchronous should be understood.
If you are not familiar with it, you can read this blog: - there are examples
[Spring] Spring Advanced Topics - Multithreading - TaskExecutor

@EnableScheduling

The @EnableScheduling annotation enables support for scheduled tasks.

That is, literally, turn on support for scheduled tasks!
Generally, the cooperation of @Scheduled annotation is required.

See this blog for details:
[Spring] Spring Advanced Topics - Scheduled Tasks - @EnableScheduling

@EnableWebMVC

The @EnableWebMVC annotation is used to enable Web MVC configuration support.

That is, it will be used when writing Spring MVC.

@EnableConfigurationProperties

The @EnableConfigurationProperties annotation is used to enable support for the @ConfigurationProperties annotation configuration bean.

That is, the @EnableConfigurationProperties annotation tells Spring Boot to enable support for @ConfigurationProperties

@EnableJpaRepositories

The @EnableJpaRepositories annotation enables support for Spring Data JPA Repostory.

The Spring Data JPA framework is mainly aimed at the only business logic code that Spring has not simplified. So far, developers have saved the only remaining work to implement the business logic of the persistence layer. The only thing to do is to declare the interface of the persistence layer. , and the rest is handed over to Spring Data JPA to help you!

Simply put, Spring Data JPA is a framework for persisting data.

@EnableTransactionManagement

The @EnableTransactionManagement annotation enables support for annotated transactions.

The annotation @EnableTransactionManagement informs Spring that @Transactional annotated classes are surrounded by transactional aspects. This way @Transactional can be used.

@EnableCaching

The @EnableCaching annotation enables annotated caching support

Through these simple @Enable*, you can open the support of a function, so as to avoid configuring a lot of code yourself, which greatly reduces the difficulty of use.

Let's observe the source code of these @Enable* annotations together, and we can find that all annotations have an @Import annotation.

The @Import annotation is used to import configuration classes, which means that these automatically enabled implementations actually import some automatically configured beans.

These import configuration methods are mainly divided into the following three types.

Three types of @Import annotation import configuration methods

The first category: directly import the configuration class
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.scheduling.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
import org.springframework.scheduling.annotation.SchedulingConfiguration;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({SchedulingConfiguration.class})
@Documented
public @interface EnableScheduling {
}

Directly import the configuration class SchedulingConfiguration, which is annotated with @Configuration and registers a scheduledAnnotationProcessor Bean. The source code is as follows:

/*
 * Copyright 2002-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.scheduling.annotation;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.scheduling.config.TaskManagementConfigUtils;

/**
 * {@code @Configuration} class that registers a {@link ScheduledAnnotationBeanPostProcessor}
 * bean capable of processing Spring's @{@link Scheduled} annotation.
 *
 * <p>This configuration class is automatically imported when using the
 * @{@link EnableScheduling} annotation. See {@code @EnableScheduling}'s javadoc
 * for complete usage details.
 *
 * @author Chris Beams
 * @since 3.1
 * @see EnableScheduling
 * @see ScheduledAnnotationBeanPostProcessor
 */
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class SchedulingConfiguration {

    @Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
        return new ScheduledAnnotationBeanPostProcessor();
    }

}
The second category: select the configuration class according to the conditions

EnableAsync annotation core code:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {
    Class<? extends Annotation> annotation() default Annotation.class;
    boolean proxyTargetClass() default false;
    AdviceMode mode() default AdviceMode.PROXY;
    int order() default Ordered.LOWEST_PRECEDENCE;

}

AsyncConfigurationSelector selects the configuration class to be imported through conditions.
The root interface of AsyncConfigurationSelector is ImportSelector. This interface needs to rewrite the selectImports method, and perform precondition judgment in this method.

In the following source code, if adviceMode is PORXY, the configuration class ProxyAsyncConfiguration is returned.
If activeMode is ASPECTJ, return AspectJAsyncConfiguration configuration class.
The source code is as follows:

public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {

    private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
            "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";

    /**
     * {@inheritDoc}
     * @return {@link ProxyAsyncConfiguration} or {@code AspectJAsyncConfiguration} for
     * {@code PROXY} and {@code ASPECTJ} values of {@link EnableAsync#mode()}, respectively
     */
    @Override
    public String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
            case PROXY:
                return new String[] { ProxyAsyncConfiguration.class.getName() };
            case ASPECTJ:
                return new String[] { ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME };
            default:
                return null;
        }
    }

}
The third category: dynamic registration of beans
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
    boolean proxyTargetClass() default false;
}

AspectJAutoProxyRegistrar predefines the ImportBeanDefinitionRegistrar interface. The role of ImportBeanDefinitionRegistrar is to automatically add beans to existing configuration classes at runtime by overriding the method:

@Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)

Among them, the AnnotationMetadata parameter is used to obtain the annotation on the current configuration class; the
BeanDefinittionRegistry parameter is used to register the Bean.
The source code is as follows:

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 enableAJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAJAutoProxy.getBoolean("proxyTargetClass")) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
    }
}

This article was written by [Anyi], all rights reserved.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324745226&siteId=291194637