Spring 是一款目前主流的 Java EE 轻量级开源框架 ,是 Java 世界最为成功的框架之一。Spring 由“Spring 之父”Rod Johnson 提出并创立,其目的是用于简化 Java 企业级应用的开发难度和开发周期。
自 2004 年 4 月,Spring 1.0 版本正式发布以来,Spring 已经步入到了第 5 个大版本,也就是我们常说的 Spring 5。
Spring基础的是 Spring Framework,其功能有:
Spring Framework 在开发中的作用:
分层解耦 - 让单体应用的可扩展性更强
整合框架 - 整合第三方框架,使之协同工作
实用技术 - 自身强大,提供各种实用功能
Spring体系结构
Spring体系分为应用层技术、中间层技术、底层核心容器和Test测试
应用技术层
中间层技术
底层核心容器
Test测试:
控制反转:(Inversion of Control,缩写为IoC)把创建对象的权利交给Spring,由Spring创建Bean对象并保存到Spring容器中,也叫IoC容器。
之前对象如何来的?
new出来的
如果使用了Spring之后,对象那里来?
由Spring创建并保存到Spring容器/IoC容器中,我们从Spring容器中获取对象
当Spring扫描到以下注解时,就会创建Bean对象保存到Spring容器中
注意:Spring默认是加载引导类/启动类所在包及其子包中所有带有以上注解的类,创建这些类的对象,保存到Spring容器中。
Spring容器启动时,会把其中的bean都创建好,如果想要主动获取这些 bean,可以使用容器的如下方法
根据类型获取 bean - T getBean(Class requiredType)
根据名称获取 bean - Object getBean(String name)
根据名称和类型获取 bean - T getBean(String name, ClassrequiredType)
在类上使用@scope注解定义Bean的作用域,Spring支持五种作用域,后三种在web环境才生效。
@Scope(""):
使用位置:写在类上
作用:指定Bean的作用范围。singleton表示单例bean,默认值。prototype表示多例bean。
如果要管理的对象来自于第三方,这时是无法用@Component等注解来实现的,解决方案:使用**@Configuration注解定义配置类,在配置类中定义方法使用@Bean**注解将方法返回的对象保存到Spring容器中。
@Configuration
//该类是一个配置类,spring会创建配置类对象保存到Spring容器中,会序会被自动调用配置类中被@Bean注解标注方法
public class DataSourceConfig {
@Bean
//spring调用该方法,将该方法的返回值保存到spring容器中
public DruidDataSource druidDataSource() {
//1.手动创建DruidDataSource对象
DruidDataSource dataSource = new DruidDataSource();
//2.设置连接参数
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///db1?useSSL=false");
dataSource.setUsername("root");
dataSource.setPassword("root");
//3.返回连接池对象,保存到spring容器中
return dataSource;
}
}
依赖注入:Dependency Injection,缩写为DI。就是指被 Spring管理的Bean对象之间的依赖关系。由Spring容器完成对象属性的赋值。
@Autowired:按照类型自动注入,如果Spring容器中同类型的对象有多个,可能注入失败,需要使用@Qualifier注解指定要注入的Bean的名称。
作用:给对象类型的属性赋值,可以用在成员变量、成员方法、构造方法上
@Controller
public class UserController {
@Autowired
private UserService userService;
public void foo() {
System.out.println("UserController.foo().......");
userService.foo();
}
}
@Autowired
public void foo() {
System.out.println("UserController.foo().......");
userService.foo();
}
//要求:有参构造方法唯一。如果有空参构造,则Spring默认使用空参构造创建对象
public UserController(@Autowired UserService userService) {
this.userService = userService;
}
@Qualifier:结合@Autowired注解一起使用,指定要注入的Bean的名称。
@Service("userServiceImplA") //给UserServiceImplA取个名称
public class UserServiceImplA implements UserService {
@Override
public void foo() {
System.out.println("UserServiceImpl.foo()-AAA执行了...");
}
}
@Service("userServiceImplB") //给UserServiceImplB取个名称
public class UserServiceImplB implements UserService {BB
@Override
public void foo() {
System.out.println("UserServiceImpl.foo()-BBB执行了...");
}
}
@Controller
public class UserController {
@Autowired
@Qualifier("userServiceImplA")//根据名称指定要注入的Bean
private UserService userService;
}
@Value:常写在成员变量上,给成员变量注入普通类型的数据
作用:给普通类型(基本类型、包装类类型、Sring类型)的属性赋值。
应用场景:变化的配置信息写死在java代码中不好,建议放入配置文件,Spring Boot采用application.properties 作为配置文件,可以使用 @Value注解结合EL表达式根据key读取配置文件中对应的value值。
@Configuration
//该类是一个配置类,spring会创建配置类对象保存到Spring容器中,会序会被自动调用配置类中被@Bean注解标注方法
public class DataSourceConfig {
@Value("${druid.driverClassName}")
private String driverClassName;
@Value("${druid.username}")
private String username;
@Value("${druid.url}")
private String url;
@Value("${druid.password}")
private String password;
}
application.properties
# 配置Druid连接池的连接参数
druid.driverClassName=com.mysql.jdbc.Driver
druid.url=jdbc:mysql:///db1?useSSL=false
druid.username=root
druid.password=root
@ConfigurationProperties:写在类上,给Bean的属性批量注入普通类型数据。
@ConfigurationProperties(prefix = "druid")
//作用:给普通类型的属性按照指定前缀
@Configuration
//该类是一个配置类,spring会创建配置类对象保存到Spring容器中,会序会被自动调用配置类中被@Bean注解标注方法
public class DataSourceConfig {
private String driverClassName;
private String username;
private String url;
private String password;
}
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
import org.junit.jupiter.api.Test;//junit5的导包
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest//表示该类是一个SpringBootTest单元测试类
class Spring01ApplicationTests {
@Autowired//从容器中获取同类的bean对象赋值给成员变量
private UserController userController;
@Test
void contextLoads() {
userController.foo();
}
}
//@SpringBootTest(classes = Spring01Application.class)//springboot测试程序入口
作用:使用了lombok工具包,就不需要手动 Alt Insert 生成构造方法、getter和setter方法、toString等方法
org.projectlombok
lombok
@Data//生成getter构造、setter构造、hashCode和equals方法、toString方法、空参构造
@AllArgsConstructor //生成全参构造
@NoArgsConstructor //生成空参构造
public class User {
private String name;
private Integer age;
private Date birthday;
}
使用@Slf4j注解,然后使用log对象进行日志输出,代替System.out.println()输出。
@Slf4j
class Spring01ApplicationTests {
@Test
void contextLoads() {
userController.foo();
log.info("userController = {}", userController);
}
现象:A对象内部注入了B对象,B对象内部注入了A对象,此现象就成为循环依赖。
解决:springboot2.6.0及以后版本需要在application.properties开启运行set方法循环依赖:
# 允许set方式循环依赖
spring.main.allow-circular-references=true
异常信息:The dependencies of some of the beans in the application context form a cycle.
只要能打破循环依赖的局面,让一个对象先初始化完就行了
@Component
public class C {
private D d;
public C(@Lazy D d) {//此处@Lazy表示创建D的代理对象而不是真实对象
this.d = d;
System.out.println("C对象创建了,d的class对象为"+d.getClass());
}
}
@Component
public class D {
private C c;
public D(C c) {
this.c = c;
System.out.println("D对象创建了,c的class对象为"+c.getClass());
}
}
注解名称 | 位置 | 注解作用 | 备注 |
---|---|---|---|
@SpringBootApplication | 引导类 | 标识 SpringBoot 程序入口 | 每个项目(module)只能有一个引导类 |
@SpringBootTest | 测试类 | 标注测试入口 | 与引导类要同包 |
@Component | 类 | 标注该注解的类由Spring管理 | 必须处于扫描范围内 |
@Controller | 类 | 同上,特定用于控制器类 | |
@Service | 类 | 同上,特定用于业务逻辑类 | |
@Repository | 类 | 同上,特定用于数据访问类 | |
@ComponentScan | 类 | 控制扫描范围 | 隐含在 @SpringBootApplication 中 |
@Scope | 类 | 控制 scope | 取值常见的有 singleton 与 prototype |
@PostConstruct | 成员方法 | 表示该方法为初始化方法 | 方法需无参,无返回值 |
@PreDestroy | 成员方法 | 表示该方法未销毁方法 | 方法需无参,无返回值 |
@Lazy | 类 | 表示该类延迟创建 | 用到时才会创建和初始化 |
@Bean | 成员方法 | 方法的返回结果由Spring管理 | 方法参数带按类型装配功能 |
@Autowried | 成员方法 | 方法参数根据类型装配 | |
@Autowried | 构造方法 | 方法参数根据类型装配 | 如果只有一个有参构造可以省略 |
@Autowried | 成员变量 | 成员变量根据类型装配 | |
@Value | 成员变量 | 成员变量根据 ${key} 找 value | 键值信息存于 application 配置文件中 |
@Value | 参数 | 方法参数根据 ${key} 找 value | 键值信息存于 application 配置文件中 |
@ConfigurationProperties | 类 | 类的成员与 key 绑定 | 键值信息存于 application 配置文件中 |
@Data | 类 | 生成空参构造/getter/setter/toString等方法 | |
@Slf4j | 类 | 生成log对象,log.info(“”)进行日志输出 |
@Controller、@Service、@Component、@Configuration、@Bean、@Autowired、@Value、@ConfigurationProperties写在哪?作用是什么?
作用:告诉Spring创建Bean对象
作用:管理第三方Bean
作用:从容器中获取同类的bean对象赋值给成员变量
@Value
@ConfigurationProperties
上,把service层交给Spring管理
作用:告诉Spring创建Bean对象
作用:管理第三方Bean
作用:从容器中获取同类的bean对象赋值给成员变量
@Value
@ConfigurationProperties
作用:用来读取配置文件中的信息