1、maven 配置(配一次就可以)
maven的目录下的config\settings文件
<!-- maven使用阿里云的镜像,这样下载依赖很快 -->
<mirrors>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
<!-- maven使用jdk1.8进行项目编译,这样避免项目开发中的一些问题 -->
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
2、创建Maven工程,pom.xml中导入依赖
<!-- 父工程 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<!-- web开发的依赖 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
3、创建主程序
创建boot层的包,在包下创建一个类作为主程序类
/**
* 主程序类
* @SpringBootApplication:说明这是一个SpringBoot应用
*/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
4、业务程序
在boot层下创建controller层,并将业务类写入该包下
@RestController // @Controller+@ResponseBody的合体
public class HelloController {
@RequestMapping("/hello")
public String handle01(){
return "Hello,Spring Boot 2 你好";
}
}
5、测试:直接运行主程序中的main方法
运行成功后,在浏览器中访问localhost:8080/hello即可
6、springboot的简化配置
springboot的配置文件在resources中创建,取名为application.properties
里面可配置tomcat启动的端口号等一系列内容,详情看官方文档
server.port=8888
7、简化部署
在pom.xml中把项目打成jar包并添加插件
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
在target目录下打开终端控制器,输入java -jar xxx.jar就可以访问localhost:8080/hello
注意:取消cmd的快速编辑模式
8、springboot特点
8.1、依赖管理
父项目做依赖管理
依赖管理
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
他的父项目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制
开发导入starter场景启动器
1、见到很多 spring-boot-starter-* : *就某种场景
2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
3、SpringBoot所有支持的场景
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
4、见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
5、所有场景启动器最底层的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
无需关注版本号,自动版本仲裁
1、引入依赖默认都可以不写版本
2、引入非版本仲裁的jar,要写版本号。
可以修改默认版本号
1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
8.2、自动配置
- 自动配好Tomcat
- 自动配好SpringMVC
- 自动配好web常见功能,如:字符编码过滤器
- 默认的包结构
- 各种配置拥有默认值
- 按需要加载所有自动配置项
9、容器功能
9.1、组件添加
9.1.1 @Configuration
之前需要在xml配置文件中用bean标签配置组件,根据id和class配置并依赖注入属性值
现在用@Configuration注解标识一个类来进行配置,被标识的类作为配置类
/**
* 1、配置类里面使用@Bean标注在方法上给容器注册组件,默认是单实例的
* 2、配置类本身也是组件
* 3、proxyBeanMethods:代理bean的方法
* Full(proxyBeanMethods = true)会在容器中找组件
* Lite(proxyBeanMethods = false)容器中不会保存代理对象,每次调用都会产生新的对象
* 场景:组件依赖
* 如果不依赖这些组件,用false,springboot启动速度加快
* 如果需要组件间依赖,用true,保证依赖的组件是容器中的组件
*/
@Configuration(proxyBeanMethods = true) //告诉springboot这是一个配置类
public class MyConfig {
/**
* 外部无论对配置类中的这个组件注册方法调用多少次,获取的都是之前注册容器中的单实例对象
* @return
*/
@Bean("user01") //给容器中添加组件,以方法名作为组件的id也可以自己写id,返回类型就是组件类型,返回的值就是组件在容器中的实例
public Per per01(){
Per per = new Per("张三", 18);
//user01组件依赖了Pet组件,在proxyBeanMethods = true时成立
per.setPet(pet01());
return per;
}
@Bean
public Pet pet01(){
return new Pet("小白",3);
}
}
/**
* 主程序类
* @SpringBootApplication:这个一个SpringBoot应用
*/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
//1、返回IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//2、查看容器里面的组件
String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
//3、从容器中获取组件,获取的组件默认是单例的
Per user01 = run.getBean("user01", Per.class);
Per user02 = run.getBean("user01", Per.class);
System.out.println("组件:" + (user01==user02));//true
//配置类本身也是组件,代理对象
MyConfig bean = run.getBean(MyConfig.class);
System.out.println(bean);
//如果@Configuration(proxyBeanMethods = true)代理对象调用方法
//springboot总会检查这个组件是否在容器中存在,如果有就不会新建,保持组件单实例
//如果@Configuration(proxyBeanMethods = false)拿到的两个对象不再相等
Per per = bean.per01();
Per per01 = bean.per01();
System.out.println(per==per01);//true
Per per1 = run.getBean("user01", Per.class);
Pet pet = run.getBean("pet01", Pet.class);
System.out.println(user01.getPet() == pet);//true
}
}
9.1.2 @Bean、@Component、@Controller、@service、@Repository
按以前的用法配置即可
9.1.3 @ComponentScan、@Import
* 4、@Import({User.class, DBHelper.class})
* 给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
*
*
*
*/
@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
}
9.1.4 @Conditional
条件装配:满足Conditional指定的条件,则进行组件注入
在主程序类中进行测试,把配置类中的pet01方法上的@Bean标签先注释掉
boolean user01 = run.containsBean("user01");
System.out.println("容器中是否存在user01组件:"+ user01);//true
boolean pet01 = run.containsBean("pet01");
System.out.println("容器中是否存在pet01组件:"+ pet01);//false
配置类的bean方法上加@ConditionalOnBean(name = “pet01”)注解
表示当容器中有这个名字的组件时才会给容器注入当前组件,没有则不注入
另外@ConditionalOnBean(name = “pet01”)也可以加载配置类上,表示有当前名字的组件时,类中的代表bean方法才会生效
@Configuration(proxyBeanMethods = true) //告诉springboot这是一个配置类
public class MyConfig {
@ConditionalOnBean(name = "pet01")//当容器中有pet01的组件给容器中注入user01,没有则不注入
@Bean("user01") //给容器中添加组件,以方法名作为组件的id,返回类型就是组件类型,返回的值就是组件在容器中的实例
public Per per01(){
Per per = new Per("张三", 18);
//user01组件依赖了Pet组件,proxyBeanMethods = true成立
per.setPet(pet01());
return per;
}
// @Bean
public Pet pet01(){
return new Pet("小白",3);
}
}
重新执行主程序类
boolean user01 = run.containsBean("user01");
System.out.println("容器中是否存在user01组件:"+ user01);//false
boolean pet01 = run.containsBean("pet01");
System.out.println("容器中是否存在pet01组件:"+ pet01);//false
9.2 原生配置文件引入
9.2.1 @ImportResource(翻译:导入资源)
如果用到了spring的配置文件来配置bean组件,想在配置类中引入这些组件,那么需要在配置类上面加上@ImportResource(“classpath:bean.xml”)注解,classpath后面写spring的配置文件的名字
bean.xml
<bean id="haha" class="com.atguigu.boot.bean.Per">
<property name="age" value="18"/>
<property name="name" value="小明"/>
</bean>
<bean id="hehe" class="com.atguigu.boot.bean.Pet">
<property name="name" value="小白"/>
<property name="age" value="3"/>
</bean>
MyConfig.java配置类加注解
@ImportResource("classpath:bean.xml")//导入spring的配置文件
//让里面配置的bean组件生效
MainApplication主程序类
boolean haha = run.containsBean("haha");
System.out.println("是否存在haha组件:"+ haha);//true
boolean hehe = run.containsBean("hehe");
System.out.println("是否存在hehe组件:"+ hehe);//true
9.3 配置绑定
之前使用java读取properties配置文件中数据库的账号密码,并将它封装到JavaBean中随时使用
public class getProperties {
public static void main(String[] args) throws FileNotFoundException, IOException {
Properties pps = new Properties();
pps.load(new FileInputStream("a.properties"));
Enumeration enum1 = pps.propertyNames();//得到配置文件的名字
while(enum1.hasMoreElements()) {
String strKey = (String) enum1.nextElement();
String strValue = pps.getProperty(strKey);
System.out.println(strKey + "=" + strValue);
//封装到JavaBean。
}
}
}
9.3.1 @Component + @ConfigurationProperties
创建一个bean组件 Car.java
@Component//把组件加到容器中,让它生效,只有在容器中的组件,才有springboot提供的功能
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
有参,无参构造器,setget方法,toString方法
}
springboot的配置文件application.properties
mycar.brand=BYD
mycar.price=100000
控制器层的类HelloController.java
@RestController // @Controller+@ResponseBody的合体
public class HelloController {
@Autowired
Car car;
@RequestMapping("/car")
public Car car(){
return car;
}
}
在浏览器访问localhost:8080/car 就可以看到
{"brand":"BYD","price":100000}
9.3.2 @EnableConfigurationProperties + @ConfigurationProperties
在配置类中写@EnableConfigurationProperties注解,开启属性配置功能,就不用在bean类里面写@Component注解了
//1.开启Car配置绑定功能
//2.把Car这个组件自动注册到容器中
@EnableConfigurationProperties(Car.class)
10、自动装配原理入门
10.1引导自动加载配置类
@SpringBootApplication注解底层包含下面三个主要注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
10.1.1 @SpringBootConfiguration
@Configuration 代表当前是一个配置类,说明main程序也是springboot的一个配置类,核心配置类
10.1.2 @ComponentScan
指定扫描哪些包,参考Spring注解;
10.1.3 @EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
@AutoConfigurationPackage 自动配置包
源码:
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}
@Import:给容器中导入一个组件
利用Registrar给容器中导入一系列组件
将指定的一个包下的所有组件导入进来?main程序所在的包下所有的组件
@Import(AutoConfigurationImportSelector.class)
源码:
1、利用getAutoConfigurationEntry(annotationMetadata)这个方法给容器中批量导入一些组件---127个组件
2、再调用方法里的List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
获取所有的需要导入到容器中的配置类
3、利用工厂加载Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader)
得到所有组件
4、从META-INF/spring.factories位置来加载一个文件。
默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories
文件里面写死了springboot一启动就要给容器中加载的所有配置类
10.2按需开启自动配置项
虽然我们127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration
按照条件装配规则(@Conditional),最终会按需配置。