spring高级话题-@enable***注解的工作原理

牵着妞去散步      2022-02-17     584

关键词:

出自:http://blog.csdn.net/qq_26525215

@EnableAspectJAutoProxy

@EnableAspectJAutoProxy注解 激活Aspect自动代理

<aop:aspectj-autoproxy/>

 

开启对AspectJ自动代理的支持。

在用到AOP的自动代理的时候用,如果你理解了Java的动态代理,很容易的就会熟悉AOP的自动代理的。

@EnableAsync

@EnableAsync注解开启异步方法的支持。 
这个相信大家都比较熟悉的。对于异步应该都理解的。 
不太熟悉的,可以看这篇博客:-有示例 
【Spring】Spring高级话题-多线程-TaskExecutor

@EnableScheduling

@EnableScheduling注解开启计划任务的支持。

也就是字面上的意思,开启计划任务的支持! 
一般都需要@Scheduled注解的配合。

详情见此博客: 
【Spring】Spring高级话题-计划任务[email protected]

@EnableWebMVC

@EnableWebMVC注解用来开启Web MVC的配置支持。

也就是写Spring MVC时的时候会用到。

@EnableConfigurationProperties

@EnableConfigurationProperties注解是用来开启对@ConfigurationProperties注解配置Bean的支持。

也就是@EnableConfigurationProperties注解告诉Spring Boot 使能支持@ConfigurationProperties

@EnableJpaRepositories

@EnableJpaRepositories注解开启对Spring Data JPA Repostory的支持。

Spring Data JPA 框架,主要针对的就是 Spring 唯一没有简化到的业务逻辑代码,至此,开发者连仅剩的实现持久层业务逻辑的工作都省了,唯一要做的,就只是声明持久层的接口,其他都交给 Spring Data JPA 来帮你完成!

简单的说,Spring Data JPA是用来持久化数据的框架。

@EnableTransactionManagement

@EnableTransactionManagement注解开启注解式事务的支持。

注解@EnableTransactionManagement通知Spring,@Transactional注解的类被事务的切面包围。这样@Transactional就可以使用了。

@EnableCaching

@EnableCaching注解开启注解式的缓存支持

通过这些简单的@Enable*可以开启一项功能的支持,从而避免自己配置大量的代码,很大程度上降低了使用难度。

我们一起来观察下这些@Enable*注解的源码,可以发现所有的注解都有一个@Import注解。

@Import注解是用来导入配置类的,这也就是说这些自动开启的实现其实是导入了一些自动配置的Bean。

这些导入配置方式主要分为以下三种类型。

@Import注解导入配置方式的三种类型

第一类:直接导入配置类

//
// 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 {
}

 

直接导入配置类SchedulingConfiguration,这个类注解了@Configuration,且注册了一个scheduledAnnotationProcessor的Bean,源码如下:

/*
 * 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();
    }

}

 

第二类:依据条件选择配置类

EnableAsync 注解核心代码:

@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

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

 

AspectJAutoProxyRegistrar 事先了ImportBeanDefinitionRegistrar接口,ImportBeanDefinitionRegistrar的作用是在运行时自动添加Bean到已有的配置类,通过重写方法:

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

 

其中,AnnotationMetadata参数用来获得当前配置类上的注解; BeanDefinittionRegistry参数用来注册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 enableAJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAJAutoProxy.getBoolean("proxyTargetClass")) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
    }

}

 

 









spring高级话题

...注解和元注解3.1、理论3.2、示例所有代码示例必须配置好SpringSpring项目的快速搭建.本系列是为了给后面学习SpringBoot打好基础,所以本系列的目的不是详细讲解Spring的知识点,而是将工作中常用的知识点罗列出来,由于SpringBoot用... 查看详情

springboot高级原理分析--@import注解(代码片段)

01:SpringBoot高级原理分析–SpringBoot自动配置:Condition02:SpringBoot高级原理分析–切换内置web服务器03:SpringBoot高级原理分析–@Enable*注解、@Import注解04:SpringBoot高级原理分析–@Import注解05:SpringBoot高级原理分析–@EnableA... 查看详情

spring高级话题

所有代码示例必须配置好SpringSpring项目的快速搭建.1、ApringAware1.1、理论SpringAware的目的就是为了让Bean获得Spring容器的服务。Spring提供的Aware接口:BeanNameAware:获得容器中的Bean的名称;BeanFactoryAware:获得当前beanfactory,这样容易... 查看详情

spring@enable模块装配的注解及编程实现方式,及包括“注解方式”,“编程方式”的自定义模块装配方式(代码片段)

前言通过模式注解的方式加载单一Bean,那如果有相关联的一系列Bean需要加载,是不是意味着每个被关联的类都需要单独加载呢?并不是哦!对于相关联的多个类。我们可以使用Enable方式同时加载多个类。同时Enabl... 查看详情

springboot高级原理分析--@enableautoconfiguration注解(代码片段)

01:SpringBoot高级原理分析–SpringBoot自动配置:Condition02:SpringBoot高级原理分析–切换内置web服务器03:SpringBoot高级原理分析–@Enable*注解、@Import注解04:SpringBoot高级原理分析–@Import注解05:SpringBoot高级原理分析–@EnableA... 查看详情

springboot中enable注解

  这句话可以作为理解springboot自动注入的原理的钥匙:ImportSelector接口的selectImports返回的数组(类的全类名)都会被纳入到spring容器中.  至于spring怎么根据类名创建bean的就不用管了。博文地址https://www.jianshu.com/p/464d04c36fb1p... 查看详情

springboot的@enable*注解的使用介绍

...以存放数组类型的。@Import用来导入一个或多个类(bean被spring容器托管)、或者配置类(配置类里面的Bean都会被spring容 查看详情

spring注解总结

目录Spring注解大全1.声明bean的注解2.注入bean的注解3.java配置类相关注解4.切面(AOP)相关注解5.@Bean的属性支持6.@Value注解7.环境切换8.异步相关9.定时任务相关10.@Enable*注解说明11.测试相关注解12.SpringMVC部分Spring注解大全1.声明bean... 查看详情

springboot高级原理分析--自定义redis-starter(代码片段)

01:SpringBoot高级原理分析–SpringBoot自动配置:Condition02:SpringBoot高级原理分析–切换内置web服务器03:SpringBoot高级原理分析–@Enable*注解、@Import注解04:SpringBoot高级原理分析–@Import注解05:SpringBoot高级原理分析–@EnableA... 查看详情

spring高级应用

1.实验目的1、掌握spring的注解使用2、深入理解注解的实现过程3、掌握事务管理的配置以及切面的注解配置2.实验内容1、通过对@Compoent注解的解读深入理解各个层注解的使用;2、通过@Before、@After的方式实现切面的通... 查看详情

spring4.1.8扩展实战之八:import注解(代码片段)

欢迎访问我的GitHub在spring框架下做开发时,@Import是常见的注解,可以用来动态创建bean,今天我们先从源码分析原理,再用实战来验证Import的作用;文章概览本章由以下几部分组成:从Enable前缀的注解谈起,揭示常见的Enable注解... 查看详情

升职加薪必备架构图springboot学习路线汇总(建议收藏)

  前言:     在以前传统Spring去做Java开发中,大量XML文件存在项目中,导致项目变得笨重繁琐、开发和部署效率也降低。前几年推出的SpringBoot提升了Spring开发者体验。集成了大量常用第三方库配置、零配置开箱... 查看详情

升职加薪必备架构图springboot学习路线汇总(建议收藏)

  前言:     在以前传统Spring去做Java开发中,大量XML文件存在项目中,导致项目变得笨重繁琐、开发和部署效率也降低。前几年推出的SpringBoot提升了Spring开发者体验。集成了大量常用第三方库配置、零配置开箱... 查看详情

springboot:如何书写一个自定义的enable*注解

...nfigurationType1。参考链接:http://www.java-allandsundry.com/2015/04/spring-enable-annotation-writing-custom.html 查看详情

day51~(spring注解高级ioc)51

第一部分:Spring的IOC一、设计模式-工厂模式 工厂模式是我们最常用的实例化对象模式了,它是用工厂中的方法代替new创建对象的一种设计模式。 我们以Mybatis的SqlSession接口为例,它有一个实现类DefaultSqlSession,如果我们... 查看详情

spring_总结_04_高级配置之条件注解@conditional(代码片段)

一、前言本文承接上一节:Spring_总结_04_高级配置(一)之Profile在上一节,我们了解到Profile为不同环境下使用不同的配置提供了支持,那么Profile到底是如何实现的呢?其实Profile正是通过条件注解来实现的。 条件注解的应用场... 查看详情

@enable*注解的原理

在SpringBoot中,我们很多的功能都能够通过@Enable*注解的方式来开启。  @EnableAspectJAutoProxy开启对自动代理的支持。  @EnableAsync开启异步方法的支持。  @EnableConfigurationProperties开启对@ConfigurationPropertis注解配置Bean的支持。通... 查看详情

关于@profile@conditional@primary@qualifier及@scope等实现高级装配的spring注解

1、关于@Profile注解的介绍@Profile注解主要用在针对不同环境而条件选择的注入bean在开发过程中由于环境的不同,我们可能在针对某些功能,需要开发不同的实现,然而在某种环境中,只能激活其中一种实现,其他的实现处于不激... 查看详情