查看源码的注解
接上一篇,我们写了一个简单demo后,可以通过:
按住ctrl键,点击某个方法、注解,进去源码之后,右上角会出现下载源码,点击下载,之后就可以看到英文的注释,接着在对应方法、注解上按ctrl+q 可以看到对应注释
@EnableAutoConfiguration
就是先根据classpath引入了哪些依赖,然后猜测你要使用哪些配置,然后自动配置。
如果多个controller应该如何操作:
就是main方法不能出现在controller里面,一个端口不能启动两个tomcat,也就不能启动两个main方法,应该独立出来;自动配置也是一样,启动一次就可以
SpringBoot引入一个全局的引导类
(放到基包下,是springboot应用入口)
@EnableAutoConfiguration//启动springboot应用的自动配置
@ComponentScan //类似于<context:componnet-scan base-package="">
public class TextApplication {
public static void main(String[] args) {
SpringApplication.run(TextApplication.class,args);
}
}
@ComponentScan
配置组件扫描,类似于context:componnet-scan,可以通过指定base-package的值来扫描特定的包;如果未指定,会从这个类所在包进行扫描,以及它所包含的所有包。
使用@SpringBootApplication优化注解
组合注解,相当于@EnableAutoConfiguration+@ComponentScan+@SpringBootConfiguration
@SpringBootConfiguration
相当于@Configuration注解
声明一个类是java配置类
应用应该只能包含一个@SpringBootConfiguration,这个注解已经在组合注解内部了,也就是后面无需自己添加。
默认配置原理
SpringBoot的默认配置方式无序任何的xml。
发展
通过配置一个德鲁伊(Druid)连接池来进行一个对比:
先添加pom依赖
<dependency>
<groupId>com.github.drtrang</groupId>
<artifactId>druid-spring-boot2-starter</artifactId>
<version>1.1.10</version>
</dependency>
创建一个config包,添加JdbcConfiguration类
@Configuration //声明一个类是一个java配置类,相当于一个xml配置文件
public class JdbcConfiguration {
@Bean //将方法的返回值注入给spring容器
public DataSource dataSource(){
new DruidDataSource().var //idea快捷补全代码小技巧
return
}
}
new DruidDataSource().var
+table键
这里可以通过这样的方式idea会自动补全代码 如下
DruidDataSource dataSource = new DruidDataSource();
@Configuration //声明一个类是一个java配置类,相当于一个xml配置文件
public class JdbcConfiguration {
@Bean //将方法的返回值注入给spring容器
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
//设置四大参数,这里不写死,先去添加资源文件
dataSource.setDriverClassName();
dataSource.setUrl();
dataSource.setUsername();
dataSource.setPassword();
return
}
}
添加资源文件
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:65535:21sb
jdbc.username=root
jdbc.password=123456
接着完善JdbcConfiguration
这里使用@Value("${}")来引入资源文件的值
@Bean将方法的返回值dataSource注入到spring容器
@Configuration //声明一个类是一个java配置类,相当于一个xml配置文件
@PropertySource("classpath:jdbc.properties")//读取资源文件
public class JdbcConfiguration {
@Value("${jdbc.driverClassName}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean //将方法的返回值注入给spring容器
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(this.driverClassName);//加this代表这是全局变量
dataSource.setUrl(this.url);
dataSource.setUsername(this.username);
dataSource.setPassword(this.password);
return dataSource;
}
}
再到HelloController类
我们使用@Autowired的方式来注入dataSource属性
@RequestMapping("hello2")
@RestController//@Controller+@ResponseBody 返回的是json的数据
@EnableAutoConfiguration//自动配置
public class HelloController2 {
@Autowired
private DataSource dataSource;
@GetMapping("show2")
public String test(){
return "hello springboot2";
}
}
接着打一个断点,进行debug
回到调试点开this
向下面划找到我们注入的四大参数
spring底层就是基于java的配置方式来进行注入的。
可以看到,这里面dataSource属性如果在其他类就不能使用了,需要再次注入了,存在代码冗余问题。
springboot的方案是:定义一个属性读取类
我们创建一个JdbcProProperties类
加上@ConfigurationProperties注解
报红了,没有关系
直接关掉这个提示
@ConfigurationProperties
点开这个注解:
发现这里的注入方式是与前缀有关的,但是这个注解提供读取资源文件的功能
当我们SpringBoot程序启动的 时候会读取一个application.properties的文件,这也是我们放所有配置的文件。然鹅,如何区分这里哪些是jdbc的配置哪些是其他的呢?就是根据我们这个@ConfigurationProperties
注解里的前缀属性prefix=""
来区分了
@ConfigurationProperties(prefix = "jdbc")
public class JdbcProProperties {
//这里已经不需要@Value注解了
private String driverClassName;
private String url;
private String username;
private String password;
//通过alt+ins 快速生成 get和set方法
public String getDriverClassName() {
return driverClassName;
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
定义相应属性之后,通过set()方法来设置相应参数,注意set属性字段名一定要和资源文件里面的一致
否则,读取不到。
回到JdbcConfiguration中
填加:启用属性读取类的注解
@EnableConfigurationProperties(JdbcProProperties.class)
接下来去掉多余注解:
//@PropertySource(“classpath:jdbc.properties”)
//注入属性的地方 改为 使用@Autowrid注入JdbcProProperties这个属性读取类
SpringBoot的第一个注入方法:
@Configuration //声明一个类是一个java配置类,相当于一个xml配置文件
//@PropertySource("classpath:jdbc.properties")//读取资源文件
@EnableConfigurationProperties(JdbcProProperties.class)
public class JdbcConfiguration {
@Autowired
private JdbcProProperties jdbcProProperties;
/* @Value("${jdbc.driverClassName}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;*/
@Bean //将方法的返回值注入给spring容器
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(this.jdbcProProperties.getDriverClassName());//加this代表这是全局变量
dataSource.setUrl(this.jdbcProProperties.getUrl());
dataSource.setUsername(this.jdbcProProperties.getUsername());
dataSource.setPassword(this.jdbcProProperties.getPassword());
return dataSource;
}
}
再次进行debug结果如下:
第二个注入方法:
不使用@Autowrid注解
采用构造方法的方式
@Configuration //声明一个类是一个java配置类,相当于一个xml配置文件
//@PropertySource("classpath:jdbc.properties")//读取资源文件
@EnableConfigurationProperties(JdbcProProperties.class)
public class JdbcConfiguration {
// @Autowired
private JdbcProProperties jdbcProProperties;
public JdbcConfiguration(JdbcProProperties jdbcProProperties){
this.jdbcProProperties = jdbcProProperties;
}
/* @Value("${jdbc.driverClassName}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;*/
@Bean //将方法的返回值注入给spring容器
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(this.jdbcProProperties.getDriverClassName());//加this代表这是全局变量
dataSource.setUrl(this.jdbcProProperties.getUrl());
dataSource.setUsername(this.jdbcProProperties.getUsername());
dataSource.setPassword(this.jdbcProProperties.getPassword());
return dataSource;
}
}
依然是可以读取到对应的参数的
第三个注入方法:
直接通过bean方法的形参来配置
@Configuration //声明一个类是一个java配置类,相当于一个xml配置文件
//@PropertySource("classpath:jdbc.properties")//读取资源文件
@EnableConfigurationProperties(JdbcProProperties.class)
public class JdbcConfiguration {
@Bean //将方法的返回值注入给spring容器
public DataSource dataSource(JdbcProProperties jdbcProProperties){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(jdbcProProperties.getDriverClassName());//加this代表这是全局变量
dataSource.setUrl(jdbcProProperties.getUrl());
dataSource.setUsername(jdbcProProperties.getUsername());
dataSource.setPassword(jdbcProProperties.getPassword());
return dataSource;
}
}
结果依然没有问题
第四个注入方法:
也是最精简的方法
@Configuration //声明一个类是一个java配置类,相当于一个xml配置文件
public class JdbcConfiguration {
@Bean //将方法的返回值注入给spring容器
@ConfigurationProperties(prefix = "jdbc")
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
return dataSource;
}
}
@ConfigurationProperties这个注解在类上的时候,会调用类的set()方法注入参数,在方法上也一样,会调用DataSource的set()方法,也会注入。debug依然ok的。
SpringBoot的四种属性注入方法总结:
- @Autowrid注入
- 构造方法注入
- @Bean方法形参注入
- 直接在@Bean方法上使用@ConfigurationProperties(prefix = “jdbc”)
第四种看起来很好,但是需要保证:
- 返回值(上面的dataSource)有相应的set()方法
- 资源文件配置要和属性名一致
有一定的局限性。
平常使用最多的是第一种方法。
这两篇文章所包含的注解