Spring简介
概念:是一个java技术框架,简化了企业开发的难度和开发周期。
作用:1、分层解耦。2、简化框架的使用难度。
Spring Boot简介
概念:基于Spring的框架。
作用:简化了Spring框架开发的难度(省去了Spring的很多配置)
SpringBoot的快速入门
创建项目
创建UserService
public interface UserService {
void foo();
}
@Service
public class UserServiceImplA implements UserService {
@Override
public void foo() {
System.out.println("UserServiceImplA.foo()...");
}
}
在引导类中获取UserService实现类对象,并调用方法
@SpringBootApplication//表示该类是SpringBoot程序入口
public class Spring01Application {
public static void main(String[] args) {
//1 返回值为Spring容器对象
ConfigurableApplicationContext ac = SpringApplication.run(Spring01Application.class, args);
//2 从Spring容器中获取UserService实现类对象
UserService userService = ac.getBean(UserService.class);
//3 调用UserService的foo方法
userService.foo();
}
}
IoC概念
控制翻转:将创建Bean对象的权利交给Spring,Spring创建Bean对象之后保存到Spring容器中,我们程序从Spring容器中获取需要的Bean对象就行了。
加载Bean(告诉Spring创建Bean对象)
@Component:写类上,将普通类交给Spring管理,这个类非三层架构中的类。
@Controller:写类上,把controller层类交给Spring管理(学习SpringMVC会用到)
@Service:写类上,把service层类交给Spring管理。
例如:
@Service
public class UserServiceImpl implements UserService {...}
@Repository:写类上,把dao层类交给Spring管理。(但是现在很少用,因为dao层使用的是mybatis技术,没有类只有接口)
注意:Spring默认加载引导类所在包及其子包下面的类上的注解,如果我们的类不在这个包范围内,无法被加载。可以在引导类上使用@ComponentScan("...")注解指定要扫描的包。
获取Bean
getBean(...)方法
根据类型获取 bean - ==<T> T getBean(Class<T> requiredType)==,返回值是方法参数传入的类型
可以传递父类型,返回子类型
可以传递接口类型,返回实现类型
根据 id 获取 bean - ==Object getBean(String name)==,返回值是Object类型,后期自己需要强转
根据 id 获取 bean - ==<T> T getBean (String name, Class<T> requiredType)==,返回值是方法参数传入的类型
Bean的范围
@Scope("") //指定Bean的作用范围
使用位置:写在类上
singleton - 容器内同 id 的 bean 只有一个实例(不加默认)
prototype - 每次使用该 bean 时会创建新的实例
request - 在 web 环境中,每个请求范围内会创建新的实例
session - 在 web 环境中,每个会话范围内会创建新的实例
application- 在 web 环境中,每个应用范围内会创建新的实例
Bean的生命周期
@PostConstruct:写在方法上,定义该方法是初始化方法
在bean被创建之后调用
@PreDestroy:写在方法上,定义该方法是销毁的方法
singleton范围的bean,在容器关闭前被调用
注:默认情况下 singleton范围的的 bean 是容器创建时就会创建,如果希望用到时才创建,可以使用 @Lazy注解标注在类上来延迟创建
管理第三方Bean
如果要管理的对象来自于第三方,这时是无法用@Component等注解来实现的
解决方法:使用@Configuration注解定义配置类,在配置类中定义方法使用@Bean注解将返回返回的对象保存到Spring容器中。
依赖注入(DI)
常用来读取配置文件中的信息
给对象类型的属性赋值
@Autowired:按照类型自动注入,如果Spring容器中同类型的对象有多个,可能注入失败,需要使用@Qualifier注解指定要注入的Bean的名称。
@Qualifier:结合@Autowired注解一起使用,指定要注入的Bean的名称。
给普通类型的属性赋值
@Value:常写在成员变量上,给成员变量注入普通类型的数据
@ConfigurationProperties:写在类上,给Bean的属性批量注入普通类型数据。
lombok工具包
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
@Data//生成除全参外所有构造方法
@Slf4j //类中会生成一个log对象,用于输出日志
@AllArgsConstructor //生成全参构造
@NoArgsConstructor //生成空参构造
Spring循环依赖
现象:A对象内部注入了B对象,B对象内部注入了A对象,此现象就成为循环依赖。
set方式循环依赖
springboot2.6.0之前:不需要解决,Spring自动解决了。
springboot2.6.0及以后版本:需要在application.properties开启运行set方法循环依赖:
spring.main.allow-circular-references=true //允许set方式循环依赖
构造方式循环依赖
必须人为解决:在任意一方构造方法中使用@Lazy注解标注注入的对象,含义是注入代理对象而非真实对象。
public C(@Lazy D d){
this.d=d;
log.info("C对象创建...,d的类型是:" + d.getClass())
}
一些问题:
问题1:请描述IoC和DI的区别?
IoC:控制反转,把创建对象的权利交给Spring,由Spring创建Bean对象并保存到Spring容器/IoC容器中,我们程序从Spring容器中获取Bean对象即可。
DI:依赖注入,告诉Spring在创建对象的时候给对象的属性赋值
问题2:请描述IoC配置四个注解的使用场景?
@Component –把普通类交给 Spring管理,这个类不属于三层架构中的类
@Controller - 把控制器类交给 Spring管理(学习SpringMVC会用到)
@Service - 把业务层类交给 Spring管理
@Repository - 把数据访问层类交给Spring管理(用得少,因为与 MyBatis 整合)
问题3:请描述@Configuration和@Bean注解写在哪?有什么作用?
@Configuration:写在类上,表示该类是一个配置类,spring加载到这个注解之后会创建这个类的对象存起来。
@Bean:写在方法上,将方法的返回值保存到Spring容器中,默认名称是方法名首字母小写
问题4:请求描述@Autowired和@Qualifier注解写在哪?有什么作用?
@Autowired:常写在成员变量,给对象类型的属性赋值,默认按照类型自动注入,如果Spring容器中同类型的对象有多个,可能注入失败。
@Qualifier:指定要注入的Bean的名称,这个注解在成员变量上不能单独使用。
问题5:请求描述@Value和@ConfigurationProperties注解写在哪?有什么作用?
@Value:常写在成员变量上,给成员变量注入普通类型的数据
@ConfigurationProperties:写在类上,给Bean的属性批量注入普通类型数据。
问题6:请求描述什么情况下Spring会查询循环依赖?如何解决?
现象:A对象内部注入了B对象,B对象内部注入了A对象,此现象就成为循环依赖。
解决set方式循环依赖:
springboot2.6.0之前:不需要解决,Spring自动解决了。springboot2.6.0及以后版本:需要在application.properties开启运行set方法循环依赖:
解决构造方式循环依赖:在任意一方构造方法中使用@Lazy注解标注注入的对象,含义是注入代理对象而非真实对象