Spring boot简介
Spring Boot
是伴随着Spring4.0
产生的,是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring
应用的初始搭建以及开发过程。该框架使用了特定的方式进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。
Spring Boot
让我们的Spring
应用变得更轻量化。比如:你可以仅仅依靠一个Java类来运行Spring
引用。你也可以打包你的应用为jar并通过使用java –jar
来运行你的Spring Web应用。
- Spring Boot的主要优点:
为所有Spring开发者更快的入门
开箱即用,提供各种默认配置来简化项目配置
内嵌式容器简化web项目
没有冗余代码生成和xml配置的要求
尽可能的根据项目依赖来自动配置Spring框架。
提供可以直接在生产环境中使用的功能,如性能指标,应用信息和应用健康检查。
Spring Boot
的缺点
依赖太多,随便的一个Spring Boot
应用都有好几十M
缺少服务的注册和发现等解决方案,可以结合springcloud
的组件使用。
缺少监控集成方案、安全管理方案(有但简单,满足不了生产的指标)
简单demo
使用maven
构建项目,官方现在稳定版本是1.5.4,第一个入门demo不是web项目,pom依赖如下:
UTF-8
1.8
1.8
org.springframework.boot
spring-boot-starter-parent
1.5.4.RELEASE
org.springframework.boot
spring-boot-starter
实体User
类:
package com.zhihao.miao.bean;
import org.springframework.stereotype.Component;
@Component
public class User {
private String username = "zhihao.miao";
private int age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
'}';
}
}
配置类:
package com.zhihao.miao.bean;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import java.util.HashMap;
import java.util.Map;
@SpringBootConfiguration
public class ConfigurationTest {
@Bean
public Map createMap(){
Map map = new HashMap();
map.put("username","zhihao.miao");
map.put("age",27);
return map;
}
}
入口类Application
:
package com.zhihao.miao;
import com.zhihao.miao.bean.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import java.util.Map;
@SpringBootApplication
public class Application {
@Bean
public Runnable createRunnable(){
return () -> System.out.println("spring boot is running");
}
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class,args);
context.getBean(Runnable.class).run();
System.out.println(context.getBean(User.class));
Map map = (Map) context.getBean("createMap");
int age = (int) map.get("age");
System.out.println("age=="+age);
}
}
项目结构目录
启动程序,以main
方法启动:
打印出正确的结果。
spring boot is running
User{username='zhihao.miao', age=0}
age==27
来分析一下流程,为何Runnable
类,User
,Map
会纳入spring容器。
首先我们分析的就是入口类Application
的启动注解@SpringBootApplication
,进入源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
....
发现@SpringBootApplication
是一个复合注解,包括@ComponentScan
,和@SpringBootConfiguration
,@EnableAutoConfiguration
。
@SpringBootConfiguration
继承自@Configuration
,二者功能也一致,标注当前类是配置类,并会将当前类内声明的一个或多个以@Bean
注解标记的方法的实例纳入到srping
容器中,并且实例名就是方法名。
-
@EnableAutoConfiguration
的作用启动自动的配置,@EnableAutoConfiguration
注解的意思就是Springboot
根据你添加的jar包来配置你项目的默认配置,比如根据spring-boot-starter-web
,来判断你的项目是否需要添加了webmvc
和tomcat
,就会自动的帮你配置web项目中所需要的默认配置。在下面博客会具体分析这个注解,快速入门的demo实际没有用到该注解。 -
@ComponentScan
,扫描当前包及其子包下被@Component
,@Controller
,@Service
,@Repository
注解标记的类并纳入到spring容器中进行管理。是以前的
(以前使用在xml中使用的标签,用来扫描包配置的平行支持)。所以本demo中的User为何会被spring
容器管理。
根据上面的理解,上面的入口类Application
,我们可以使用:
package com.zhihao.miao;
import com.zhihao.miao.bean.User;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import java.util.Map;
@ComponentScan
public class Application {
@Bean
public Runnable createRunnable(){
return () -> System.out.println("spring boot is running");
}
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class,args);
context.getBean(Runnable.class).run();
System.out.println(context.getBean(User.class));
Map map = (Map) context.getBean("createMap");
int age = (int) map.get("age");
System.out.println("age=="+age);
}
}
使用@ComponentScan
注解代替@SpringBootApplication
注解,也可以正常运行程序。原因是@SpringBootApplication
中包含@ComponentScan
,并且springboot
会将入口类看作是一个@SpringBootConfiguration
标记的配置类,所以定义在入口类Application
中的Runnable
也可以纳入到容器管理。
SpringBootApplication参数详解
- Class>[] exclude() default {}:
根据class来排除,排除特定的类加入spring容器,传入参数value类型是class类型。
- String[] excludeName() default {}:
根据class name来排除,排除特定的类加入spring容器,传入参数value类型是class的全类名字符串数组。 - String[] scanBasePackages() default {}:
指定扫描包,参数是包名的字符串数组。 - Class>[] scanBasePackageClasses() default {}:
扫描特定的包,参数类似是Class类型数组。
看一个demo学会使用这些参数配置
在包下com.zhihao.miao.springboot定义一个启动应用类(加上@SpringBootApplication注解)
package com.zhihao.miao.springboot;
import com.zhihao.miao.beans.Cat;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
Cat cat = context.getBean(Cat.class);
System.out.println(cat);
}
}
在com.zhihao.miao.beans包下定义一个实体类,并且想将其纳入到spring容器中,
public class Cat {
}
package com.zhihao.miao.beans;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfig {
@Bean
public Cat cat(){
return new Cat();
}
}
启动启动类,打印结果如下:
说明Cat类并没有纳入到spring容器中,这个结果也如我们所想,因为@SpringBootApplication只会扫描@SpringBootApplication注解标记类包下及其子包的类(特定注解标记,比如说@Controller,@Service,@Component,@Configuration和@Bean注解等等)纳入到spring容器,很显然MyConfig不在@SpringBootApplication注解标记类相同包下及其子包的类,所以需要我们去配置一下扫包路径。
修改启动类,@SpringBootApplication(scanBasePackages = "com.zhihao.miao"),指定扫描路径:
package com.zhihao.miao.springboot;
import com.zhihao.miao.beans.Cat;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication(scanBasePackages = "com.zhihao.miao")
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
Cat cat = context.getBean(Cat.class);
System.out.println(cat);
}
}
启动并打印:
当然使用@SpringBootApplication(scanBasePackageClasses = MyConfig.class),指定scanBasePackageClasses参数的value值是你需要扫描的类也可以,结果一样,不过如果多个配置类不在当前包及其子包下,则需要指定多个。
再看一个列子,
在上面的列子的相同包下(com.zhihao.miao.springboot)配置了People,并将其纳入到spring容器中(@Component),我们知道@SpringBootApplication注解会扫描当前包及其子包,所以People类会纳入到spring容器中去,我们需要将其排除在spring容器中,如何操作?
可以使用@SpringBootApplication的另外二个参数(exclude或excludeName)
package com.zhihao.miao.springboot;
import org.springframework.stereotype.Component;
@Component
public class People {
}
启动类,
package com.zhihao.miao.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
People people = context.getBean(People.class);
System.out.println(people);
}
}
启动并打印结果:
然后修改@SpringBootApplication配置,
package com.zhihao.miao.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication(exclude = People.class)
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
People people = context.getBean(People.class);
System.out.println(people);
}
}
很明显启动报错。使用@excludeName注解也可以。如下,
@SpringBootApplication(excludeName = {"com.zhihao.miao.springboot.People"})
参考文档:
Springboot1.5.4官方文档