废话不多,赞也别少,兄弟们好,开整!
? 众所周知,SpringBoot默认会扫描启动类所在的包及其子包,一般我们都是在需要的类上通过注解的方式去【Compoment、Controller、Service、Respository】将Bean注册交给IOC进行管理,但是注册第三方Bean的方案却不支持直接在类上写这个(read-only),但是我们可以在其他地方使用@Bean或者@Import注解将三方Bean进行注册。
【tips:】前面是引入,不算白雪,也可以直接看每个的最终版,结果测试在@Bean的第一个案例里面
@SpringBootApplication
public class 启动类 {
【测试方法都可以用这个 后续的案例就不在一一输出了】
public static void main(String[] args) {
//获取容器用于检查容器内部是否有对应的Bean对象
ApplicationContext context = SpringApplication.run(启动类.class, args);
//获取对应的Bean对象
Country aBean = context.getBean(A.class);
//检验输出
System.out.println(aBean);
}
/**
* @Bean
* public 三方类名 三方类名小写(){
* return new 三方类构造方法();
* }
*/
//注入第三方的Bean A对象到IOC容器里面
@Bean
public A a() {
return new A();
}
}
【“白雪”警告!】在这里需要几个Bean对象就可以写几个Bean,但是不建议这样写
因为这是在启动类里,启动类启动类 干的就是启动的活,或者用一句更嘿嘿的话说:这样写不够美观
所以,'【不建议大家这样写】
配置类的的路径必须在???(默认扫描的路径中)
配置类MyConfig
@Configuration//告诉Spring 给哥们把这个玩意弄上
public class MyConfig {
/**
* @Bean
* public 三方类名 三方类名小写(){
* return new 三方类构造方法();
* }
*/
@Bean
public A a() {
return new A();
}
/**
* 创建的对象默认名字就是其方法名
* 可以通过name属性对其进行赋值
*/
@Bean
public B b(){
return new B();
}
/**
* 注意!!!
* 如果当我们声明的第三方Bean对象创建需要依赖其他的
(已经存在IOC容器中的)Bean对象的时候
* 直接在其形式参数列表里进行声明即可
* */
@Bean
public C c(A a){
return new C();
}
}
实际开发中,最常导入的类一般为【配置类、ImportSelector接口实现类】
@Import(???.class) 这里的配置类,不用写注解(@Configuration)了,也不用在默认扫描路径之下了
@SpringBootApplication
public class 启动类 {
}
这个类可以是任意类,有多个怎么办?看下图,参数可以用数组的!蒙鼓人!
@Import({A.class,B.class...})
-那我要是有一百个怎么办?
-(那你写一百个呗),那肯定不够优雅啊,
-那咋办呢?
-那不还有一个ImportSelector接口实现类么,
-我&……%¥#*()()*……&*……&*……%&%
简单版
1、自定义ImportSelector接口实现类
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//返回【全类名】的数组,有多少写多少
// return new String[]{"com.why.config.MyConfig"};
return new String[]{配置类1.class.getName(),配置类2.class.getName()};
}
}
2、启动类
@Import(MyImportSelector.class)
@SpringBootApplication
public class 启动类 {
}
最终版(建议啊建议大家用(手动狗头),讲一下每一步骤)
最终版就是更加优雅的版本,解耦合,便于维护,易于更改(程序猿)
区别:使用配置文件 将所有需要加载的配置类放进去
1、编写配置文件
将每一个需要加载的类的全类名编写到文件的每一行(每个类独占一行)
2、编写ImportSelector的实现类
在实现类里面读取配置文件
3、在启动类中使用@Import注解进行引入
【1、配置文件 test.configs】
配置类全类名1
配置类全类名2
...
=================================================
【2、自定义ImportSelector的实现类】
public class CommmonImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
List<String> imports = new ArrayList<>();//存放每一个配置类的全类名 的集合
/**
* 通过类加载器去获取一个名为test.imports的资源作为输入流
* 注意:1、要访问的资源文件的路径
* 2、getResourceAsStream()返回的输入流需要进行适当的关闭处理
* */
InputStream is = CommmonImportSelector.class.//获取CommmonImportSelector的Class对象
getClassLoader().//获得该类的类加载器
getResourceAsStream("test.imports");//通过类加载器获取资源,就是尝试找这个文件并将其转为输入流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
while(true){
try {
if (!((line = br.readLine()) != null)) break;
} catch(IOException e) {
throw new RuntimeException(e);
}finally {
if(br != null){
try {
br.close();
} catch(IOException e) {
throw new RuntimeException(e);
}
}
}
imports.add(line);
}
//这里是将集合对象转为数组对象,但是需要传入一个数组对象作为参数来指定返回数组的类型和大小,传递一个空的数组作为参数,是要根据运行时集合的大小自动创建一个合适大小的数组
return imports.toArray(new String[0]);
return imports.toArray(String[]::new);// >= JDK11
}
}
======================================================================
【3、启动类】
@Import(MyImportSelector.class)
@SpringBootApplication
public class 启动类 {
}
好了,学到这里就完事了,后续是装波一阶段,【白雪警告!!!】
什么,你说启动类上加一堆这玩意不好看,怎么办,雪啊,你看看SpringBootApplication这个注解 不就是一个混合注解么,你也搞一个把它塞进去不就完事了
不爱装的雪玩写的启动类
@SpringBootApplication
@Import(CommmonImportSelector.class)
public class SbRegisterApplication {
}
真是没有逼格,看会装的怎么写吧
1、编写自定义的注解类
//@Target 指定目标类型 ElementType.TYPE表示只能在类、接口或枚举类上
@Target(ElementType.TYPE)
//@Retention 指定它们在代码中的保留策略,即注解在什么时候保留有效
//RUNTIME 表示被注解的注解在运行时保留,
@Retention(RetentionPolicy.RUNTIME)
//嘿嘿 没想到吧 老弟|妹儿 还是它
@Import(CommmonImportSelector.class)
public @interface EnableMyConfig {
}
2、学过装(博弈)的写的启动类
@SpringBootApplication
@EnableMyConfig
public class SbRegisterApplication {
}
你就说比起来简洁不简洁吧,雪了两分半的芝士,那能是假的么!一点都不白雪!!!