不是银趴~是@Import!

这篇具有很好参考价值的文章主要介绍了不是银趴~是@Import!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

首先我们要明确:@Import 注解是 Spring 提供的。

然后我们看一下该注解的官方注释:

Indicates one or more component classes to import — typically @Configuration classes.

Provides functionality equivalent to the <import/> element in Spring XML. Allows for importing @Configuration classes, ImportSelector and ImportBeanDefinitionRegistrar implementations, as well as regular component classes (as of 4.2; analogous to AnnotationConfigApplicationContext.register).

@Bean definitions declared in imported @Configuration classes should be accessed by using @Autowired injection. Either the bean itself can be autowired, or the configuration class instance declaring the bean can be autowired. The latter approach allows for explicit, IDE-friendly navigation between @Configuration class methods.

May be declared at the class level or as a meta-annotation.

If XML or other non-@Configuration bean definition resources need to be imported, use the @ImportResource annotation instead.

我们将其中我们关心的重要部分提取出来翻译整理如下:

  • 该注解可导入一个或多个组件类——通常是Configuration类。

  • 允许导入@Configuration类、ImportSelector接口和ImportBeanDefinitionRegistrar接口的实现,以及普通类(从4.2版本开始)。

  • @Import注解可以在类上声明,也可以作为元注解声明在其他注解上。

那么 @Import 注解到底有什么作用和优势呢?

记住下面几句话:

导入配置。

从各个地方、通过各种方式导入配置。

在你需要的时候,从各个地方、通过各种方式导入配置。

在你需要的时候,从各个地方、通过各种方式导入并改造成你喜欢的配置。


下面我们通过示例讲 4 种官方注释给出的导入类型,分别是:

  • 普通类

  • @Configuration类

  • ImportSelector接口实现

  • ImportBeanDefinitionRegistrar接口实现

普通类

普通类不必啰嗦,有手就行。

public class Circle {
}
@Configuration
@Import({Circle.class})
public class MainConfig {
}

导入@Configuration类

我们建立三个不同的模块,MainModule, Module1, Module2。

让 MainModule 引入 Module1、Module2依赖。

在 MainModule 中创建 MainConfig 类如下:

@Configuration
@Import({Config1.class, Config2.class})
public class MainConfig {
}

很明显,Config1,Config2 分别属于2个模块,如下:

@Configuration
public class Config1 {
    @Bean
    public String config1() {
        return "我是config1配置类!";
    }
}
@Configuration
public class Config2 {
    @Bean
    public String config2() {
        return "我是config2配置类!";
    }
}

在 MainModule 中创建测试类看是否生效:

@Test
void contextLoads() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
    for (String name : context.getBeanDefinitionNames()) {
        System.out.println(String.format("%s->%s", name, context.getBean(name)));
    }
}

测试结果如下:

mainConfig->com.example.annotation.config.MainConfig$$EnhancerBySpringCGLIB$$a98d5b6a@55a609dd
com.example.module1.config1->com.example.module1.config.Config1$$EnhancerBySpringCGLIB$$72aca5d0@4afd21c6
config1->我是config1配置类!
com.example.module2.config2->com.example.module2.config.Config2$$EnhancerBySpringCGLIB$$72aca5d0@4afd21c6
config2->我是config2配置类!

ImportSelector接口实现

首先我们需要认识一下 ImportSelector 接口:

public interface ImportSelector {

    String[] selectImports(AnnotationMetadata importingClassMetadata);

    @Nullable
    default Predicate<String> getExclusionFilter() {
        return null;
    }
}

只有一个需要实现的方法:

selectImports

参数 AnnotationMetadata 是什么?

翻译为注解元数据。

有什么用?

用来获取被@Import标注的类上面所有的注解信息。

String[] 是什么?

返回需要导入的类名的数组,可以是任何普通类,配置类。

上示例:

创建一个配置类

@Configuration
public class Config {
    @Bean
    public String name() {
        return "公众号:JavaCode";
    }
}

定义一个ImportSelectors实现类

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{
                Config.class.getName()
        };
    }
}

上述代码中需要说明一下,Config.class.getName() 得到的是类的全类名,也就是[包名.类名],也就是com.example.annotation.pojo.Config。

导入MyImportSelector

@Import({MyImportSelector.class})
public class MainConfig {
}

这时候有人问了:

这里怎么没有 @Configuration 注解?

没关系哈,虽然 @Import 注解通常是与 @Configuration 注解一起使用的,但不是绝对必要的。

ImportBeanDefinitionRegistrar接口实现

首先我们还是先认识一下 ImportBeanDefinitionRegistrar 接口:

public interface ImportBeanDefinitionRegistrar {

    default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
        registerBeanDefinitions(importingClassMetadata, registry);
    }
    default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    }
}

可以看到只有2个方法,第一个方法调用第二个方法,所以我们就只看第二个方法就好了。

AnnotationMetadata 我们前边说过了:

用来获取被@Import标注的类上面所有的注解信息。

BeanDefinitionRegistry 呢?

它是一个接口,内部提供了注册bean的各种方法,用于我们手动注册bean。

上示例:

创建一个 Java 类

public class Rectangle {
    public void sayHi() {
        System.out.println("Rectangle sayHi()");
    }
}

创建 ImportBeanDefinitionRegistrar 实现类

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Rectangle.class);
        // 注册一个名字叫做 rectangle 的 bean
        registry.registerBeanDefinition("rectangle", rootBeanDefinition);
    }
}

总结

第一种:

我们有什么就可以导什么。

第二种:

我们可以把分散的配置集中起来,更加清晰和有组织。

第三种:

除了我们模块现有的配置,你只要能拿到类的全类名,就能注册进来。

第四种:

我们不光能到处拿,我们还能拿来以后随便改!

以上四种方式就实现了我们当初的豪言:

导入配置。

从各个地方、通过各种方式导入配置。

在你需要的时候,从各个地方、通过各种方式导入配置。

在你需要的时候,从各个地方、通过各种方式导入并改造成你喜欢的配置。


● 终于搞懂动态代理了!

● 学会@ConfigurationProperties月薪过三千

● 学一点关于JVM类加载的知识

● Java注解,看完就会用

● Java反射,看完就会用

● @Value是个什么东西

不是银趴~是@Import!文章来源地址https://www.toymoban.com/news/detail-778291.html

到了这里,关于不是银趴~是@Import!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Tomcat启动失败,启动子级时出错 IllegalStateException,因为我们有相同的WebServlet注解配置路径,有两个相同的上下文路径,所以会报错。

      这是一个关于Tomcat启动Web项目时出现异常的报错信息。报错信息中提到了一个IllegalStateException异常,这个异常通常是由于Tomcat在启动子级时出现了错误导致的。具体来说,这个异常可能是由于以下原因引起的: 应用程序的上下文路径已经存在于Tomcat中,但是Tomcat正在尝试将

    2024年04月12日
    浏览(80)
  • 学好虚拟化,首先要学Linux

    上次讲到了虚拟化的基础知识,比如虚拟化的应用、各个厂商都是通过何种技术路径来实现的等等,本篇想记录一下我学习到的CPU内存虚拟化和网络虚拟化相关知识,通过记录来制造反馈,让自己更有效地学习。需要注意的是,学习虚拟化就免不了和Linux打交道了。 在此之前

    2023年04月20日
    浏览(41)
  • 加密项目是否采用DAO模式 首先考量这8个因素

    随着越来越多公司寻求管理和组织战略创新,我们看到市场对 DAO  的兴趣日益增长,同时也对人们的数字生活产生了巨大影响。不过, 并不是每个项目都适合采用 DAO 模式,在做出正确选择之前,你需要考虑以下 8 个要点: 1、集中服务和大规模项目不建议用 DAO 对于 Web3

    2024年01月22日
    浏览(45)
  • 新型网络安全:从过程到明确结果

    过去的情况 网络安全是理论性的,结果才是实际性的。这可能吗? 我们现在的努力方向 结论 本文讲述了为什么企业必须重新思考其网络安全方法:旧方法是否足够有效,是否可以完全适用?公司应采取哪些行动来实现内部信息安全的成熟度?我们将解释市场如何寻求建立网

    2024年02月13日
    浏览(46)
  • hive报错信息不明确的情况汇总

    Error: Error while processing statement: FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.MoveTask. Exception when loading 1 in table uniaction1 with loadPath=********************************* 这种报错可能出现在insert select中,也可能直接load中报错出现,对于tez引擎和mr引擎,这个报错可能会有不同的

    2024年02月16日
    浏览(49)
  • VsCode推送项目到Gitee仓库(清晰、明确、具体)

                     Tip:若已经创建过了,直接跳到第二部分看VsCode如何上传代码到Gitee 创建仓库比较简单,下面两张图就是整个过程,这里不在赘述,具体如下:                    1.打开VsCode,找到 资源管理器在 “更改”栏下选择你马上要提交到Gitee上的代码

    2023年04月16日
    浏览(38)
  • Js逆向教程-05明确js逆向的目标

    通过本地运行js代码那 实现脱离浏览器后 能够实现和浏览器上运行加密js的效果。 网站上完全都是JavaScript实现的加密,我们的目的要知道加密的整个过程,并且 本地 实现这个加密的过程,拿到和浏览器一样的加密的结果。 得到加密的结果之后就可以跳过浏览器,本地直接

    2024年02月10日
    浏览(39)
  • IDEA上传项目到Gitee仓库(清晰、明确、具体)

            Tip:若已经创建过了,直接跳到第二部分看VsCode如何上传代码到Gitee         创建仓库比较简单,下面两张图就是整个过程,这里不在赘述,具体如下:   1.打开IDEA,选择菜单栏中 \\\" VCS \\\"选项,选择 版本控制,创建本地Git仓库。如下图所示。   2.选择为“哪个

    2023年04月23日
    浏览(38)
  • Java:读取excel文件中的内容(简单、详细、明确、有全部代码)

    注意: jxl 仅支持读取 .xls 文件,读 .xlsx 会报错! 在 pom.xml 中引入 jxl 的依赖 支持读取 xlsx 文件的 poi 依赖说明、使用方法及更多详细内容可以参考: Java读取excel的方式,一篇文章看懂(详细)

    2024年02月12日
    浏览(48)
  • 电脑提示“由于仅部分匹配或匹配不明确,因此无法迁移设备”怎么办?

    “由于仅部分匹配或匹配不明确,因此无法迁移设备”错误可能会在将较旧的系统更新到较新的系统版本或者安装了双系统之后出现,此外,驱动程序不兼容、系统文件损坏、计算机接口故障、系统不支持出现错误的外接设备等也可能导致该错误出现。了解了无法迁移设备错

    2024年04月09日
    浏览(90)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包