Spring 3.1 새로운 기능 2 : @ Enable * 주석 소스 코드 및 많은 주석 활성화

@ enable * 주석
SpringBoot의 자동 구성 원칙을 분석 할 때 이러한 @ Enable * 주석의 소스 코드를 관찰 할 수 있으며 모든 주석에 @Import 주석이 있음을 알 수 있습니다. @Import 어노테이션은 구성 클래스를 가져 오는 데 사용됩니다. 이는 이러한 자동 열기 구현이 실제로 일부 자동 구성된 Bean을 가져옴을 의미합니다.
예 : FreeMarker의 자동 구성 클래스 FreeMarkerAutoConfiguration,이 자동 구성 클래스는 클래스 로더의 일부 클래스가 존재하고 다른 구성 클래스 이후에로드되어야합니다.

그러나 일부 주석 스위치를 사용할 때만 적용되는 자동화 된 구성 클래스도 있습니다. 예를 들어 spring-boot-starter-batch의 @EnableBatchProcessing 주석 및 @EnableCaching입니다.
1. 자동 주입의 예
Annotation을 정의합니다. EnableContentService를 사용하면이 주석을 사용하는 클래스가 일부 클래스를 주입하거나 낮은 수준의 작업을 수행 할 수 있습니다.
완료하려면 구성 클래스와 함께 Spring에서 제공하는 @Import 주석을 사용하십시오.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(ContentConfiguration.class)
public @interface EnableContentService {
    
    }

public interface ContentService {
    
    
    void doSomething();
}

public class SimpleContentService implements ContentService {
    
    
    @Override
    public void doSomething() {
    
    
        System.out.println("do some simple things");
    }
}

그런 다음 응용 프로그램 항목에 @EnableContentService 주석을 추가합니다.

이 경우 ContentService가 삽입됩니다. SpringBoot도 이것으로 수행됩니다. 고급 ImportSelector를 사용합니다.
@Import를 사용하는 방법.
첫 번째 범주 : 구성 클래스 직접 가져 오기
예를 들어 @EnableScheduling은 구성 클래스 SchedulingConfiguration을 직접 가져오고이 클래스에는 @Configuration 주석이 추가되고 scheduleAnnotationProcessor의 Bean이 등록됩니다.

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

두 번째 유형 : 조건에 따라 구성 클래스를 선택합니다.
예를 들어 @EnableAsync에서 구성 클래스 구성은 AsyncConfigurationSelector.class에 의해 선택됩니다.

@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는 조건을 통해 가져와야하는 구성 클래스를 선택합니다. AsyncConfigurationSelector의 루트 인터페이스는 ImportSelector입니다.이 인터페이스는 selectImports 메서드를 다시 작성하여이 메서드에서 사전 조건을 판단해야합니다.

adviceMode가 PORXY이면 구성 클래스 ProxyAsyncConfiguration이 반환됩니다.

activeMode가 ASPECTJ이면 AspectJAsyncConfiguration 구성 클래스가 반환됩니다.

주요 방법은 다음과 같습니다.

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;
        }
    }

}

세 번째 카테고리 : Bean
Spring에서 EnableAspectJAutoProxy.java의 동적 등록

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
    
    
    boolean proxyTargetClass() default false;
    boolean exposeProxy() default false;
}

AspectJAutoProxyRegistrar는 ImportBeanDefinitionRegistrar 인터페이스를 구현합니다. ImportBeanDefinitionRegistrar의 역할은 메소드를 다시 작성하여 런타임에 기존 구성 클래스에 Bean을 자동으로 추가하는 것입니다.

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.getBoolean("proxyTargetClass")) {
    
    
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
    
    
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }

}

그중 AnnotationMetadata 매개 변수는 현재 구성 클래스에 대한 주석을 가져 오는 데 사용됩니다.

BeanDefinittionRegistry 매개 변수는 Bean을 등록하는 데 사용됩니다.

SpringBoot에서 ImportSelector 사용 SpringBoot에서 ImportSelector는 SpringBoot에서
제공하는 @EnableAutoConfiguration 주석을 통해 완료됩니다.

이 @EnableAutoConfiguration 주석은 명시 적으로 호출 할 수 있습니다. 그렇지 않으면 @SpringBootApplication 주석에서 암시 적으로 호출됩니다.
@EnableAutoConfiguration 주석은 EnableAutoConfigurationImportSelector를 ImportSelector로 사용합니다. 다음 코드는 EnableAutoConfigurationImportSelector에서 선택하기위한 특정 코드입니다.

@Override
public String[] selectImports(AnnotationMetadata metadata) {
    
    
    try {
    
    
        AnnotationAttributes attributes = getAttributes(metadata);
        List<String> configurations = getCandidateConfigurations(metadata,
                attributes);
        configurations = removeDuplicates(configurations); // 删除重复的配置
        Set<String> exclusions = getExclusions(metadata, attributes); // 去掉需要exclude的配置
        configurations.removeAll(exclusions);
        configurations = sort(configurations); // 排序
        recordWithConditionEvaluationReport(configurations, exclusions);
        return configurations.toArray(new String[configurations.size()]);
    }
    catch (IOException ex) {
    
    
        throw new IllegalStateException(ex);
    }
}

getCandidateConfigurations 메소드는 구성 클래스를 가져옵니다.

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
        AnnotationAttributes attributes) {
    
    
    return SpringFactoriesLoader.loadFactoryNames(
            getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
}

SpringFactoriesLoader.loadFactoryNames 메소드는 정적 변수 FACTORIES_RESOURCE_LOCATION에 따라 모든 jar 패키지에서 META-INF / spring.factories 파일 정보를 읽습니다.

public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
    
    
    String factoryClassName = factoryClass.getName();
    try {
    
    
        Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
        List<String> result = new ArrayList<String>();
        while (urls.hasMoreElements()) {
    
    
            URL url = urls.nextElement();
            Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
            String factoryClassNames = properties.getProperty(factoryClassName); // 只会过滤出key为factoryClassNames的值
            result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
        }
        return result;
    }
    catch (IOException ex) {
    
    
        throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
                "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
    }
}

getCandidateConfigurations 메서드의 getSpringFactoriesLoaderFactoryClass 메서드는 EnableAutoConfiguration.class를 반환하므로 키 값을 org.springframework.boot.autoconfigure.EnableAutoConfiguration으로 필터링합니다.

다음 구성 코드는 자동 구성 jar 패키지의 spring.factories 파일의 일부입니다 (org.springframework.boot.autoconfigure.EnableAutoConfiguration의 키가 있으므로 이러한 자동 구성을 가져옵니다).
여기에 사진 설명 삽입

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration,\......

물론 이러한 모든 AutoConfiguration이로드되는 것은 아니며 AutoConfiguration에서 @ConditionalOnClass와 같은 조건에 따라로드할지 여부가 결정됩니다.

위의 예에서 속성 파일을 읽을 때 키가 org.springframework.boot.autoconfigure.EnableAutoConfiguration 인 값만 필터링됩니다.

로드해야하는 클래스를 필터링하는 데 사용되는 SpringBoot 내부에 몇 가지 다른 키가 있습니다.

org.springframework.test.context.TestExecutionListener

org.springframework.beans.BeanInfoFactory

org.springframework.context.ApplicationContextInitializer

org.springframework.context.ApplicationListener

org.springframework.boot.SpringApplicationRunListener

org.springframework.boot.env.EnvironmentPostProcessor

org.springframework.boot.env.PropertySourceLoader

@Enable *

@EnableAspectJAutoProxy
@EnableAspectJAutoProxy 주석은 Aspect 자동 프록시를 활성화하며 @EnableAspectJAutoProxy는 <aop : aspectj-autoproxy />와 동일하여 AspectJ 자동 프록시 지원을 활성화합니다.

@EnableAsync
@EnableAsync 주석은 비동기 메서드를 지원합니다.

링크 설명추가 하려면 "@Async 비동기 호출 구현"을 참조하십시오.

@EnableScheduling
@EnableScheduling 주석은 예약 된 작업을 지원합니다.

예를 들어 링크 설명추가 하려면 "Spring의 @Scheduled Task Scheduling"을 참조하십시오.

@EnableWebMVC
@EnableWebMVC 주석은 Web MVC 구성 지원을 활성화하는 데 사용됩니다.

Spring MVC를 작성할 때 사용합니다.

@EnableConfigurationProperties
@EnableConfigurationProperties 어노테이션은 @ConfigurationProperties 어노테이션 구성 Bean에 대한 지원을 사용하는 데 사용됩니다.

@EnableJpaRepositories
@EnableJpaRepositories 주석은 SpringData JPA Repostory에 대한 지원을 활성화합니다.
SpringData JPA 프레임 워크는 주로 Spring이 단순화하지 않은 유일한 비즈니스 로직 코드를 목표로하고 있습니다. 지금까지 개발자들은 Persistence Layer의 비즈니스 로직을 구현하기 위해 남은 작업을 절약했습니다. 지속성 계층., SpringData JPA가 나머지 작업을 수행합니다!
간단히 말해서 SpringData JPA는 데이터를 유지하기위한 프레임 워크입니다.

@EnableTransactionManagement
@EnableTransactionManagement 어노테이션은 어노테이션이있는 트랜잭션을 지원합니다.

@EnableTransactionManagement 주석은 @Transactional 주석이 달린 클래스가 트랜잭션 측면으로 둘러싸여 있음을 Spring에 알립니다. 그런 다음 @Transactional을 사용할 수 있습니다.

@EnableCaching
@EnableCaching 주석은 주석 스타일 캐싱 지원을 활성화합니다.

추천

출처blog.csdn.net/u010010600/article/details/114117469