首页 > 其他分享 >不是银趴~是@Import!

不是银趴~是@Import!

时间:2024-01-10 15:12:05浏览次数:32  
标签:不是 public 导入 注解 Import Configuration class

首先我们要明确:@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是个什么东西

标签:不是,public,导入,注解,Import,Configuration,class
From: https://www.cnblogs.com/cosimo/p/17956511

相关文章

  • Spring cloud No spring.config.import property has been defined
    *[解决SpringCloud2021.0.5版本,使用nacos做配置中心,报Nospring.config.importpropertyhasbeendefined的问题\_addaspring.config.import=nacos:propertytoyour-CSDN博客](https://blog.csdn.net/weixin_44951259/article/details/127929284)*[SpringCloud202......
  • 如何不是用 width 和 height 控制 svg 的渲染大小?
    除了使用width和height属性控制SVG的渲染大小外,还可以使用以下方法:使用CSS样式:可以通过设置CSS的width和height属性来控制SVG的渲染大小。例如,设置SVG元素的样式为width:100px;height:100px;。使用viewBox属性:viewBox属性定义了SVG的可视区域,在该区域内进行缩放和裁剪。可以通过......
  • 现在就开始准备春招,是不是太早了点?
    本文首发自公粽hao「林行学长」,欢迎来撩,免费领取20个求职工具资源包。了解校招、分享校招知识的学长来了!相信不少同学开始期待寒假了,当然,也有不少同学开始纠结:现在要不要开始准备春招?是先享受寒假,还是为春招多努力几天?大家别纠结了,现在准备春招,一点也不早……01春招的特点想要在春......
  • 15.明明是x86的sos为什么会报不是有效的Win32应用程序
    最近在分析一个dump的时候,遇到了%1不是有效的Win32应用程序。这个错误,输出如下:*************Pathvalidationsummary**************ResponseTime(ms)LocationDeferredSRV*C:\mysymbols*http://msdl......
  • 数组名不是首元素地址的情况
    1.&arr-&数组名-数组名不是首元素地址-数组名表示整个数组--&数组名,取出的是整个数组的地址2.sizeof(arr)-sizeof(数组名)-数组名表示的整个数组-sizeof(数组名)计算的是整个数组的大小#define_CRT_SECURE_NO_WARNINGS1#include<stdio.h>intmain(){ //两种数组名不是首元素......
  • AI数字员工的出现:不是取代,而是让技术更好地服务于人类_光点科技
    在人工智能技术迅猛发展的今天,AI数字员工的出现成为了企业和组织关注的热点。与传统观念中的机器人或自动化设备不同,AI数字员工是集成了最新AI技术,如自然语言处理、机器学习和情感分析等功能的虚拟助手,它们能够完成复杂的工作任务,并与人类同事进行交互。但这一进步并非旨在替代人力......
  • idea 项目加载 全线飘红, @Service飘红,连 import java.util.List; 也飘红,终极解决方案
    常规方案:1、maven,检查maven配置,重新加载maven依赖,重新加载项目,把maven的本地私库删了重新下载2、检查idea配置,jdk配置,加载的项目的配置,idea清理缓存重启,等等3、是否更新了其他idea配置,比如git忽略文件里是否添加了*.class 4、重新安装idea5、及其他以上方案自行百度,都可以......
  • import { EventEmitter } from 'eventemitter3'; class H5SSE extends EventEmitter
    import{EventEmitter}from'eventemitter3';classH5SSEextendsEventEmitter代码解析通过eventemitter3源码学习Javascript设计模式:发布-订阅(观察者模式)发布-订阅模式又叫观察者模式,它定义对象之间一对多的关系,当一个对象的状态发生变化时,所有依赖它的对象都将得到通知......
  • Nextjs SyntaxError: Cannot use import statement outside a module错误
    NextJs报 SyntaxError:Cannotuseimportstatementoutsideamodule第三方依赖不能导入问题 解决方案:1,Next.JS13.1+,可以使用next.config.js中的属性transpilePackagesconstnextConfig={transpilePackages:['the-npm-package'],//第三方的依赖};module.expo......
  • 我不是学霸,如何拿下软考高项(级)信息系统管理师证书?
    一、报班:1、因为感兴趣就咨讯了几家百度排名靠前的机构;了解考试的方式与时间别信,软考高级挺简单之类的话,学霸除外,哈哈二、系统的学习(纸本资料,视频),重点十大知识领域&计算工期与成本;书本不一定,视频三遍以上;撑握十大知识领域&47过程组,输入,输出;三、准备论文:多看,多读,多写时间有要......