springBoot @Enable* 注解的使用

时间:2021-09-23 03:44:51

1、为什么使用@springbootapplication注解,即可做到自动配置?

答:@springbootapplication,内部起作用的注解其实有3个。@enableautoconfiguration,@componentscan,@configuration。这篇文章主要是讲解@enablexx注解

2、为什么使用了@enableautoconfiguration。当使用了@configurationproperties时,即可自动导入.yml 或者.properties里面的配置项?

答:在@enableautoconfiguration内部,使用了@import注解。导入autoconfigurationimportselector帮助springboot将符合条件的configuration加载到ioc容器中。但是内部其实使用了springfactoriesloader来完成。类似与java spi的功能
,即从/meta-inf/spring.factories加载配置

?
1
2
3
4
5
6
7
@target({elementtype.type})
@retention(retentionpolicy.runtime)
@documented
@inherited
@autoconfigurationpackage
@import({autoconfigurationimportselector.class})
public @interface enableautoconfiguration

可以看到@import中,其实是导入了一个autoconfigurationimportselector的类。最关键的是,该类实现了接口importselector

?
1
2
3
4
5
6
7
8
public interface importselector {
 /**
  * select and return the names of which class(es) should be imported based on
  * the {@link annotationmetadata} of the importing @{@link configuration} class.
  */
 string[] selectimports(annotationmetadata importingclassmetadata);
 
}

这是importselector的描述,大概意思就是,该方法返回的bean 会自动的被注入,被spring所管理。

接着来看 autoconfigurationimportselector中 selectimports 的实现

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public string[] selectimports(annotationmetadata annotationmetadata) {
  if(!this.isenabled(annotationmetadata)) {
   return no_imports;
  } else {
   autoconfigurationmetadata autoconfigurationmetadata = autoconfigurationmetadataloader.loadmetadata(this.beanclassloader);
   annotationattributes attributes = this.getattributes(annotationmetadata);
   list<string> configurations = this.getcandidateconfigurations(annotationmetadata, attributes);
   configurations = this.removeduplicates(configurations);
   set<string> exclusions = this.getexclusions(annotationmetadata, attributes);
   this.checkexcludedclasses(configurations, exclusions);
   configurations.removeall(exclusions);
   configurations = this.filter(configurations, autoconfigurationmetadata);
   this.fireautoconfigurationimportevents(configurations, exclusions);
   return stringutils.tostringarray(configurations);
  }
 }

代码都写得很清楚。就不解释了。

在@import中,可以看到 有个链接指向了 importbeandefinitionregistrar。这同样是一个接口,作用跟 importselector 一样。

?
1
2
3
4
5
public interface importbeandefinitionregistrar {
 public void registerbeandefinitions(
   annotationmetadata importingclassmetadata, beandefinitionregistry registry);
 
}

在registerbeandefinitions方法中,可以用beandefinitionregistry 注入我们想要注入的bean。

代码示例:

使用@import编写自己的@enable

1、创建2个测试bean

?
1
2
3
4
5
public class role {
}
 
public class user {
}

2、自定义enable注解

?
1
2
3
4
5
6
@target({elementtype.type})
@retention(retentionpolicy.runtime)
@documented
@import(myenableautoconfig.class)
public @interface enablebean {
}

3、实现自己的enableautoconfiguration类

?
1
2
3
4
5
6
public class myenableautoconfig implements importselector{
 @override
 public string[] selectimports(annotationmetadata importingclassmetadata) {
  return new string[]{"com.xhn2.role","com.xhn2.user"};
 }
}

4、编写启动类

?
1
2
3
4
5
6
7
8
9
@enablebean
@componentscan("com.xhn2")
public class main {
 public static void main(string[] args) {
  configurableapplicationcontext context = springapplication.run(main.class, args);
  system.out.println(context.getbean(user.class));
  system.out.println(context.getbean(role.class));
 }
}

5、运行结果

com.xhn2.user@496bc455
com.xhn2.role@59402b8f

控制台成功打印。

代码示例2,自动装配第3方jar包的bean

新建maven工程

1、pom.xml

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<modelversion>4.0.0</modelversion>
 
 <groupid>org.csp</groupid>
 <artifactid>hello</artifactid>
 <version>1.0.0</version>
 
 <properties>
  <maven.compiler.source>1.8</maven.compiler.source>
  <maven.compiler.target>1.8</maven.compiler.target>
  <project.build.sourceencoding>utf-8</project.build.sourceencoding>
 </properties>
 
 <dependencies>
  <dependency>
  <groupid>org.springframework</groupid>
  <artifactid>spring-context</artifactid>
  <version>4.3.17.release</version>
  </dependency>
 </dependencies>

2、编写configuration

?
1
2
3
4
5
6
7
@configuration
public class mytest {
 @bean
 public runnable runnable() {
  return ()->{};
 }
}

在resources下新建meta-inf/spring.factories文件,加入以下配置

?
1
org.springframework.boot.autoconfigure.enableautoconfiguration=com.edu.mytest

3、将项目安装到本地maven仓库:mvn install

4、主工程引入刚才安装到本地的jar。

?
1
2
3
4
5
<dependency>
   <groupid>org.csp</groupid>
   <artifactid>hello</artifactid>
   <version>1.0.0</version>
  </dependency>

5、获取刚才配置的runnable

?
1
2
3
4
5
6
7
8
@springbootapplication
public class main {
 public static void main(string[] args) {
  springapplication application = new springapplication(main.class);
  configurableapplicationcontext context = application.run(args);
  system.out.println(context.getbean(runnable.class));
 }
}

6、控制台打印

com.edu.mytest$$lambda$153/284686302@2c07545f

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://segmentfault.com/a/1190000015188776