目录
一.Spring简介
1.什么是Spring
2.什么是容器
3.IOC
4.DI
二.创建Spring项目
1.创建一个普通的maven项目
编辑2.引入maven依赖
3.添加启动类
三.Spring的创建和使用
1.创建Bean
2.将Bean放入到容器中
3.获取Bean对象
4.创建 Spring 上下文
5.获取指定的 Bean 对象
编辑
四.Spring Bean的存
1.基于XML文件
2.基于注解
1.类注解
2.方法注解
五.Spring Bean的取
1.对象装配
1.属性注入
1.@Autowired注解
2.@Resource注解
2.Setter方法注入
3.构造函数注入
2.三种方法的优缺点
1.属性注入
2.Setter注入(Spring 3.X推荐)
3.构造函数注入(Spring 4.X推荐)
六.Bean的作用域
1.六种作用域
2.singleton
3.prototype
4. request
5. session
6. application
7. websocket:
8.设置作用域
七.Spring的启动流程
八.Bean的生命周期
1.实例化bean
2.设置属性
3.Bean初始化
4.使用Bean
5.销毁Bean
class A{
B b=new B();
}
这个B对象的生命周期是由A类来管理的,现在Spring将B的生命周期交给Spring来统一管理.这样就发生了控制权的反转.接下来你就会有疑问了,这样做有什么好处吗?为什么这样做呢?
当我们创建一个车的时候,要先创建车身,车身又需要底盘,底盘又依赖于轮胎,这样一层一层的依赖,使代码的耦合度很高,怎么样可以降低耦合度呢?我们现在只需要将各个部件都先创建好,然后当创建底盘的时候将轮胎注入,创建车身的时候将底盘注入,创建车的时候将车身注入,此时他们之间就没有很强的耦合性,而IOC容器就是做的注入和取出的功能,因此
org.springframework
spring-context
5.2.5.RELEASE
也就是一个main方法
public class App {
public static void main(String[] args) {
}
}
Bean就是Java中一个普通的对象
public class Student {
public void sayHi(){
System.out.println("hi!!!!");
}
}
Spring 配置⽂件的固定格式为以下内容:
接下来我么只需要将student对象注册到spring容器中即可
id为唯一标识这个student对象的.class为Student对象的位置
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(" spring-config.xml");
}
}
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("springconfig.xml"));
ApplicationContext VS BeanFactory(常见面试题)
- 继承关系和功能方面来说:Spring 容器有两个顶级的接口:BeanFactory 和ApplicationContext。其中 BeanFactory 提供了基础的访问容器的能力,而 ApplicationContext属于 BeanFactory 的子类,它除了继承了 BeanFactory 的所有功能之外,它还拥有独特的特性,还添加了对国际化支持、资源访问支持、以及事件传播等方面的支持。
- 从性能方面来说:ApplicationContext 是一次性加载并初始化所有的 Bean 对象(预加载),而BeanFactory 是需要那个才去加载那个(懒加载),因此更加轻量。
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(" spring-config.xml");
Student student = (Student) context.getBean("student");
student.sayHi();
}
}
通过在xml文件里定义的bean的id可以获取到相应的对象.
Student student2 = context.getBean("student", Student.class);
当xml文件中只注册了一个Student类型的对象,这种方法可以拿到这个对象,当注册了多个,会报错
Student student1 = context.getBean(Student.class);
基本流程图
上面演示的就是基于这种方式的
content:component-scan的base-package即spring扫描的包,在这些包下有spring的五大注解的类可以被加载到spring中.
五大注解@Controller @Service @Repository @Component @Configuration
每一个注解上面都有@Component,说明这几个注解都是 @Component注解的子类,所以他们实现的功能都是一样的,那为什么还要有这么多不同的注解呢?
命名规范:
注解生成bean的id为类的名称的首字母小写.当首字母和第二个字母都为大写字母的时候,直接返回原名字.
因为这些注解的作用都显示,我们这里只演示一个
@Controller
public class UserController {
public void sayHi() {
System.out.println("UserController");
}
}
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = context.getBean("userController", UserController.class);
userController.sayHi();
}
}
这五大注解中可以重命名bean的名字.比如
@Controller("uController")
这样就需要用uContoller来从spring容器中拿到UserController对象.
现在定义一个User类
@Data
public class User {
private Integer id;
private String name;
}
@Bean注解
注意:@Bean注解必须配合五大注解一起使用
@Component
public class Users {
@Bean
public User user1() {
User user = new User();
user.setId(1);
user.setName("zhangsan");
return user;
}
}
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
User user = context.getBean("user1",User.class);
System.out.println(user);
}
}
@Bean("aaa")
//含有两个id,分别为aaa和bbb
@Bean(name = {"aaa","bbb"})
@Bean注解命名规则就是方法名
还有一种参数的注入
@Bean
public String name() {
return "lisi";
}
@Bean
public User user2(String name) {
User user = new User();
user.setId(1);
user.setName(name);
return user;
}
现在要求将UserService注入到UserController类中
先来创建service类
@Service
public class UserService {
public User getUser(Integer id) {
User user = new User();
user.setId(id);
user.setName("Java-" + id);
return user;
}
}
再来创建controller类
@Controller
public class UserController {
@Autowired
UserService userService;
public User getUser(Integer id) {
return userService.getUser(id);
}
}
测试:
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = context.getBean("userController", UserController.class);
System.out.println(userController.getUser(5));
}
}
可以观察到UserService被成功注入到UserController类中.
@Autowired和@Qualifier搭配使用
@Autowired
@Qualifier("aaa") //注入名字为aaa的对象
UserService userService;
@Controller
public class UserController {
@Resource
UserService userService;
public User getUser(Integer id) {
return userService.getUser(id);
}
}
同时 @Resource注解可以注入指定名字的对象
@Resource(name = "aaa") / /代表注入name=aaa的对象
UserService userService;
区别
通过set方法,上面需要加上@Autowired注解(不可省略)
@Controller
public class UserController3 {
// 注⼊⽅法3:Setter注⼊
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
public User getUser(Integer id) {
return userService.getUser(id);
}
}
通过构造函数注入,只有一个构造函数,可以省略@Autowired注解,如果存在多个构造函数,需要在使用的那个构造函数上面加@Autowired注解,否则就会报如下错误
一个类默认有一个无参的构造函数
当我们写了有参的构造函数的时候,就没有这个默认无参构造函数了创建对象,需要调用构造函数
当前存在多个构造函数, Spring就不知道使用哪个了,所以会报错我们需要告诉Spring,使用哪个构造函数
注意:如果只有一个构造方法,那么 @Autowired 注解可以省略
@Controller
public class UserController2 {
// 注⼊⽅法2:构造⽅法注⼊
private UserService userService;
@Autowired //此时注解可省略,因为只有一个构造函数
public UserController2(UserService userService) {
this.userService = userService;
}
public User getUser(Integer id) {
return userService.getUser(id);
}
}
优点:
缺点:
优点:
缺点:
优点:
缺点:
限定程序中变量的可用范围叫做作用域,或者说在源代码中定义变量的某个区域就叫做作用域。 而 Bean 的作用域是指 Bean 在 Spring 整个框架中的某种行为模式,比如 singleton 单例作用域,就 表示 Bean 在整个 Spring 中只有一份,它是全局共享的,那么当其他人修改了这个值之后,那么另一个人读取到的就是被修改的值。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
public class Users {
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean(name = "u1")
public User user1() {
User user = new User();
user.setId(1);
user.setName("Java"); // 【重点:名称是 Java】
return user;
}
}
bean的生命周期即对象从诞生到销毁的整个过程,我们把这个过程叫做一个对象的生命周期
(为bean分配内存空间,相当于new出来一个对象,执行构造方法)
注意:不等同于初始化.
xml定义init-method
使用注解的方式@PostConstruct执行初始化方法
销毁容器的各种方法,如 @PreDestroy、DisposableBean 接口方法、destroy-method。