SpringBoot总结问题
谈谈依赖管理?
1.为什么只需要一个spring-boot-starter-web依赖就满足了大部分生产环境?为什么引入依赖可以不需要版本号?
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/>
</parent>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.4</version>
</parent>
原理:在pom.xml里,父工程parent点进去它的源码里,又有一个parent,这里面的properties属性几乎声明了开发中所有的依赖的版本号,比如消息队列mq,aspectj事务的织入,连接池,log4j日志等等。在dependencyManagement标签里,管理着所有的依赖,以及他们的版本号。
结论:因此,当我们在pom.xml里引入这个parent,然后再通过dependency的方式,就相当于引入了dependencyManagement下的所有依赖。
此外.如果spring-boot-dependencies下dependencyManagement下没有注册我们需要的依赖,那么就只能在pom下外部引入,版本号则不能省。
2.如何修改某个依赖的版本号
1.查看spring-boot-dependencies下的这个properties下默认的版本号 2.在当前项目pom.xml里重写properties下的版本号即可。根据就近原则,maven会选择我们重写的版本号进行更新依赖库。
3.关于spring启动器你的理解是?
- 启动器,就是springboot的启动场景,即spring-boot-starter,比如spring-boot-starter-web.就会自动引入web场景下的所有依赖。
- springboot会将所有的功能场景,都变成一个个的启动器,我们要使用什么功能,就用对应的启动器即可。
- spring-boot-starter-* 是spring官方的场景启动器。而 *-spring-boot-starter是第三方的场景启动器,不属于spring旗下的。比如:thirdpartyproject-spring-boot-starter。
自动配置机制?
1.自动配置机制?
- 自动配好了tomcat:依赖的引入和tomcat的配置。
- 自动配好了springMVC
1.引入了SpringMVC的全套组件以及常用组件 2.配置好了web开发所需的常见配置,比如字符编码CharacterFilter、文件上传解析器等等。 - 自动配好了注解扫描
- 各种配置拥有默认项,每个配置都会映射一个类,且每一个类都会在容器中创建对象。
- 按需加载所有的自动配置项
1.我们引入哪个启动器的场景,这个场景的自动配置才会生效 2. springboot所有的自动配置都是在启动器下的spring-boot-autoconfigure包里面:
2.为什么注解生效不再需要像SpringMVC那样配置扫描包的注解?
springboot帮我们自动配置好了注解扫描的包默认的作用域是只在主程序所在的包以及它的子包,这个属于约定大于配置,当然如果想要扩大注解生效的扫描范围,就必须在注解@SpringBootApplication(scanBasePackages=“”)通过scanBasePackages指定扫描哪个包。或者@ComponentScan指定扫描路径。
@SpringBootApplication(scanBasePackages = "com.kxy")
public class HelloWorldSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorldSpringBootApplication.class, args);
}
}
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.kxy")
public class HelloWorldSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorldSpringBootApplication.class, args);
}
}
@Configuration的底层逻辑?
@Configuration标注当前类是一个配置类,结合我们的@Bean使用,可以将一个方法的返回值对象装配到spring容器中。@Bean可携带参数,为当前这个对象组件起一个别名,相当于原生xml的方式通过bean标签的里的id或者name去为bean组件起一个别名。
springboot2的新特性:@Configuration可携带参数proxyBeanMethods。 原理:
当proxyBeanMethods的值默认为true,也就是说, 配置类组件,当我们多次调用配置类这个组件里的方法,会发现他们是一个相同的对象,这说明默认情况下,我们每次调用方法时,都是以从容器中获取组件的方式,是单例模式。 当proxyBeanMethods的值为false时,当我们多次调用配置类这个组件里的方法时,都会重新创建一个新的对象,说明每次调用方法时,都会执行一遍方法体,也就是单纯的调用普通方法,这时每次就会new一个新的对象。这种情况下,属于Lite(轻量级),能加速容器的启动。 总结:
Full模式与Lite模式:
- 配置类组件之间没有依赖关系用Lite(轻量级)模式加速容器启动过程,减少判断。
- 配置类组件之间有依赖关系用Full模式,每次都是从容器中获取到的单实例组件。
代码佐证:
@Configuration(proxyBeanMethods = true)
public class MyConfig {
@Bean("user")
public User getUser(){
return new User("kxy",18);
}
}
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(HelloWorldSpringBootApplication.class, args);
String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
User user = run.getBean("user", User.class);
MyConfig bean = run.getBean(MyConfig.class);
User user1 = bean.getUser();
User user2 = bean.getUser();
System.out.println(user1 == user2);
System.out.println(user);
}
谈谈@Import的理解?
除了@Configuration,@Component,@Service,@Resopsity这些组件 @import同样也可以将自定义的类以及第三方的类装配到容器里:像这样:
@Import({User.class})
@Configuration(proxyBeanMethods = true)
public class MyConfig {
@Bean("user")
public User getUser(){
return new User("kxy",18);
}
}
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(HelloWorldSpringBootApplication.class, args);
String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
String[] beanNamesForType = run.getBeanNamesForType(User.class);
for (String s : beanNamesForType) {
System.out.println(s);
}
}
运行结果:上面的是通过import,下面则是通过configuration的。
@什么是Conditional 条件装配?
满足@Conditional的条件时,才进行组件的注入 派生的条件注解典型有以下: @ConditionalOnBean:容器里有这个组件,才… @ConditionalOnClass:某个class位于类路径上才会实例化一个Bean @ConditionalOnExpression:当表达式为true的时候,才会实例化一个Bean @ConditionalOnMissingBean:仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean @ConditionalOnMissingClass:某个class不位于类路径上才会实例化一个Bean @ConditionalOnNotWebApplication:不是web应用
- 如果条件注解在一个类上,那么表示只有满足这个条件时,类里面所有的bean才会被注入
- 如果条件注解在某个方法上,那么只有满足这个条件时,这个bean才会被注入。
代码佐证:
@Configuration(proxyBeanMethods = true)
public class MyConfig {
@ConditionalOnMissingBean(name = "tom")
@Bean("user")
public User getUser(){
return new User("kxy",18);
}
@Bean("tom")
public Tom getTom(){
return new Tom("xx",12);
}
}
System.out.println("user是否存在容器中:"+run.containsBean("user"));
System.out.println("tom是否存在容器中:"+run.containsBean("tom"));
这段代码, @ConditionalOnMissingBean(name = “tom”),表示容器中没有tom时候,才会注入user。此时容器确实还没有,所以可以注入。待user注入完后,存在于容器中,tom才开始注入。因此说明这个@Bean也是有生命周期的,而且是自上而下的执行的。反过来,如果我把注解改成ConditionalOnBean的话,那么tom一开始没有被注入,所以不满足,因此user不会被注入。
@ImportResouce
@ImportResouce可以将某个xml文件解析成注解的方式,从而将xml中注册的bean都注入到容器中。
谈谈怎么实现配置绑定?springboot怎么通过一个配置文件管理某个类中的属性?
@Component+@ConfigurationProperties
@Data
@NoArgsConstructor
@AllArgsConstructor
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
}
于是便绑定上了application.properties
server.port=8080
mycar.brand=BYD
mycar.price=10000
spring自动装配Car,请求一个视图返回一个Json字符串形式的car对象:
@Controller
public class HelloController {
@Autowired
Car car;
@RequestMapping("/car")
@ResponseBody
public Car car(){
return car;
}
}
这样视图就会返回一个Json字符串形式的car对象:
@EnableConfigurationProperties+@ConfigurationProperties
- @EnableConfigurationProperties必须在配置类里写才能生效,@Configuration已经标注了这是配置类,就可以使用。
- @EnableConfigurationProperties的作用是开启配置绑定的功能,并且将携带的参数(一个类)注入到容器中,拥有了@Component的功能。
- 尤其是第三方不可修改的工具类,就可以用@EnableConfigurationProperties将他注入到容器中,并且配置绑定我们的Properties配置文件。
@Configuration(proxyBeanMethods = true)
@EnableConfigurationProperties(Car.class)
public class MyConfig {
@ConditionalOnBean(name = "tom")
@Bean("user")
public User getUser(){
return new User("kxy",18);
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
}
总结:通过这几种方式javaBean和配置文件一一绑定,能够方便我们在配置文件统一的修改bean的数据。
自动装配?
|