1、简单示例,读取application.properties中属性
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.edu.spring</groupId> <artifactId>springboot</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <name>springboot</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.6.RELEASE</version> <scope>import</scope> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> </dependencies> </project>
application.properties
tomcat.host=192.168.1.100
tomcat.port=8080
TomcatProperties.java使用@ConfigurationProperties读取属性
package com.edu.spring.springboot; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix="tomcat") public class TomcatProperties { private String host; private Integer port; public String getHost() { return host; } public void setHost(String host) { this.host = host; } public Integer getPort() { return port; } public void setPort(Integer port) { this.port = port; } @Override public String toString() { return "TomcatProperties [host=" + host + ", port=" + port + "]"; } }
App.java
package com.edu.spring.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class App { public static void main( String[] args ) { ConfigurableApplicationContext context=SpringApplication.run(App.class,args); System.out.println(context.getBean(TomcatProperties.class)); context.close(); } }
运行结果如下:
2、SpringBootApplication包含EnableAutoConfiguration(启动自动配置),因此使用@EnableAutoConfiguration也可以启动读取配置文件,如下
App.java
package com.edu.spring.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; @EnableAutoConfiguration @ComponentScan public class App { public static void main( String[] args ) { ConfigurableApplicationContext context=SpringApplication.run(App.class,args); System.out.println(context.getBean(TomcatProperties.class)); context.close(); } }
运行结果如下:
3、EnableAutoConfiguration装配了EnableConfigurationProperties,启动配置文件起作用的是EnableConfigurationProperties,如下
App.java
package com.edu.spring.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; @EnableConfigurationProperties @ComponentScan public class App { public static void main( String[] args ) { ConfigurableApplicationContext context=SpringApplication.run(App.class,args); System.out.println(context.getBean(TomcatProperties.class)); context.close(); } }
运行结果如下:
4、@EnableAsync、@Async异步执行,先看下面的同步执行
Jeep.java
package com.edu.spring.springboot; import org.springframework.stereotype.Component; @Component public class Jeep { public void method() { for(int i=0;i<5;i++){ System.out.println("--------------:"+i); } } }
App.java
package com.edu.spring.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class App { public static void main( String[] args ) { ConfigurableApplicationContext context=SpringApplication.run(App.class,args); context.getBean(Jeep.class).method(); System.out.println("------------------end"); context.close(); } }
运行结果如下:
可以看出是同步执行的,异步执行只需在启动类上添加@EnableAsync,在方法上添加@Async,如下:
Jeep.java
package com.edu.spring.springboot; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; @Component public class Jeep { @Async public void method() { for(int i=0;i<5;i++){ System.out.println("--------------:"+i); } } }
App.java
package com.edu.spring.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication @EnableAsync public class App { public static void main( String[] args ) { ConfigurableApplicationContext context=SpringApplication.run(App.class,args); context.getBean(Jeep.class).method(); System.out.println("------------------end"); context.close(); } }
运行结果如下,可以看到先输出了end
通过上面上面的例子可以看出:
启动读取属性配置需要在启动类上添加@EnableConfigurationProperties,在读取的类上添加@ConfigurationProperties
启动异步执行需要在启动类上添加@EnableAsync,在需要异步的方法上添加@Async。可以看到这两个Enable*注解都含有@Import
5、import注解导入类,该类会被spring容器托管,导入配置类,该配置类里的bean会被spring容器托管,如下:
User.java
package com.edu.spring.springboot; public class User { }
Role.java
package com.edu.spring.springboot; public class Role { }
MyConfig.java
package com.edu.spring.springboot; import org.springframework.context.annotation.Bean; public class MyConfig { @Bean public Runnable createRunnable(){ return () -> {}; } @Bean public Runnable createRunnable2(){ return () -> {}; } }
App.java
package com.edu.spring.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Import; @SpringBootApplication @Import({User.class,Role.class,MyConfig.class}) public class App { public static void main( String[] args ) { ConfigurableApplicationContext context=SpringApplication.run(App.class,args); System.out.println(context.getBean(User.class)); System.out.println(context.getBean(Role.class)); System.out.println(context.getBeansOfType(Runnable.class)); context.close(); } }
运行结果如下:
6、Import导入实现ImportSelector接口的类。该接口的方法selectImports返回一个数组,该数组中所有的类型都会被springboot装配成bean,如下:
MyImportSelector.java
package com.edu.spring.springboot; import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { // TODO Auto-generated method stub return new String[]{"com.edu.spring.springboot.User",Role.class.getName(),MyConfig.class.getName()}; } }
User.java
package com.edu.spring.springboot; public class User { }
Role.java
package com.edu.spring.springboot; public class Role { }
MyConfig.java
package com.edu.spring.springboot; import org.springframework.context.annotation.Bean; public class MyConfig { @Bean public Runnable createRunnable(){ return () -> {}; } @Bean public Runnable createRunnable2(){ return () -> {}; } }
App.java
package com.edu.spring.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Import; @SpringBootApplication @Import(MyImportSelector.class) public class App { public static void main( String[] args ) { ConfigurableApplicationContext context=SpringApplication.run(App.class,args); System.out.println(context.getBean(User.class)); System.out.println(context.getBean(Role.class)); System.out.println(context.getBeansOfType(Runnable.class)); context.close(); } }
运行结果如下:
通过selectImports方法可以获取Enable*注解的属性,如下:
新增注解类Enablelog.java
package com.edu.spring.springboot; 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; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(MyImportSelector.class) public @interface Enablelog { String name(); }
MyImportSelector.java,输出注解类的属性
package com.edu.spring.springboot; import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { System.out.println(importingClassMetadata.getAnnotationAttributes(Enablelog.class.getName())); return new String[]{"com.edu.spring.springboot.User",Role.class.getName(),MyConfig.class.getName()}; } }
运行结果如下:
7、Import导入实现ImportBeanDefinitionRegistrar接口的类。该接口的方法registerBeanDefinitions可以动态注入bean如下:
User.java
package com.edu.spring.springboot; public class User { }
Role.java
package com.edu.spring.springboot; public class Role { }
MyConfig.java
package com.edu.spring.springboot; import org.springframework.context.annotation.Bean; public class MyConfig { @Bean public Runnable createRunnable(){ return () -> {}; } @Bean public Runnable createRunnable2(){ return () -> {}; } }
MyImportBeanDefinitionRegistrar.java,实现ImportBeanDefinitionRegistrar接口
package com.edu.spring.springboot; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry) { BeanDefinitionBuilder bdb=BeanDefinitionBuilder.rootBeanDefinition(User.class); registry.registerBeanDefinition("user",bdb.getBeanDefinition()); BeanDefinitionBuilder bdb2=BeanDefinitionBuilder.rootBeanDefinition(Role.class); registry.registerBeanDefinition("role",bdb2.getBeanDefinition()); BeanDefinitionBuilder bdb3=BeanDefinitionBuilder.rootBeanDefinition(MyConfig.class); registry.registerBeanDefinition(MyConfig.class.getName(),bdb3.getBeanDefinition()); } }
Enablelog.java
package com.edu.spring.springboot; 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; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(MyImportBeanDefinitionRegistrar.class) public @interface Enablelog { String name(); }
App.java
package com.edu.spring.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication @Enablelog(name="this is springboot") public class App { public static void main( String[] args ) { ConfigurableApplicationContext context=SpringApplication.run(App.class,args); System.out.println(context.getBean(User.class)); System.out.println(context.getBean(Role.class)); System.out.println(context.getBeansOfType(Runnable.class)); context.close(); } }
运行结果如下:
同ImportSelector接口一样,ImportBeanDefinitionRegistrar同样可以获取注解的属性,情况下面的简单列子:
Cat.java
package com.edu.spring.springboot.bean; import org.springframework.stereotype.Component; @Component public class Cat { }
Dog.java
package com.edu.spring.springboot.bean2; import org.springframework.stereotype.Component; @Component public class Dog { }
EchoBeanPostProcessor.java
package com.edu.spring.springboot; import java.util.List; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class EchoBeanPostProcessor implements BeanPostProcessor { private List<String> packages; public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { for(String pack:packages){ if(bean.getClass().getName().startsWith(pack)){ System.out.println("echo bean :"+bean.getClass().getName()+" "+pack); } } return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } public List<String> getPackages() { return packages; } public void setPackages(List<String> packages) { this.packages = packages; } }
EchoImportBeanDefinitionRegistrar.java
package com.edu.spring.springboot; import java.util.Arrays; import java.util.List; import java.util.Map; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; public class EchoImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry) { // TODO Auto-generated method stub Map<String,Object> attr=(Map<String,Object>)importingClassMetadata.getAnnotationAttributes(EnableEcho.class.getName()); String[] packArr=(String[])attr.get("packages"); List<String> packages=Arrays.asList(packArr); System.out.println("packages: "+packages); BeanDefinitionBuilder bdb=BeanDefinitionBuilder.rootBeanDefinition(EchoBeanPostProcessor.class); bdb.addPropertyValue("packages",packages); registry.registerBeanDefinition(EchoBeanPostProcessor.class.getName(),bdb.getBeanDefinition()); } }
EnableEcho.java
package com.edu.spring.springboot; 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; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(EchoImportBeanDefinitionRegistrar.class) public @interface EnableEcho { String[] packages(); }
App.java
package com.edu.spring.springboot; import org.springframework.boot.SpringApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; @ComponentScan @EnableEcho(packages={"com.edu.spring.springboot.bean","com.edu.spring.springboot.bean2"}) public class App { public static void main( String[] args ) { ConfigurableApplicationContext context=SpringApplication.run(App.class,args); context.close(); } }
目录结果如下:
运行结果如下:
总结:springboot中在启动类上添加Enable*注解是启动springboot的某个特性,同时需要在指定的类或者方法上添加对应的注解。
SpringBootApplication注解包含了EnableAutoConfiguration注解。
EnableAutoConfiguration注解中的EnableConfigurationProperties注解是启动解析配置属性,对应ConfigurationProperties
Import注解可以装配bean。
Import注解中导入实现ImportSelector、或者ImportBeanDefinitionRegistrar接口的类来实现Enable*特性