Spring 笔记(一)
为什么要用 Spring
为了解耦!
那么何为解耦?
耦合
指程序间的依赖关系:
-
包括类之间的依赖
-
包括方法之间的依赖
解耦
-
降低程序间的依赖关系
-
做到编译的时候不依赖(报错?),运行时才依赖。
思路
- 用反射来创建对象。
- 读取配置文件来读取要创建的对象的全限定类名。
IOC 容器详解
IOC: Inversion of Control
关键词:工厂模式,单例模式,线程安全。
- 单例模式实现思路:新建静态 Map 共享 value 。
原来:
private IUserDao userDao = new UserDaoImpl();
IOC 实现:
private IUserDao userDao = (IUserDao) BeanFactory.getBean("userDao");
作用:控制反转,将控制权转移给 BeanFactory,从而割断与 Dao 层的直接联系,从而达到解耦。
注:以上的例子里,userDao 的新建对象任务已经交给了工厂。这样操作之后,编译时不会有依赖,但是运行时会有依赖。
IOC 的本质:把创建对象的权力交给框架。
Spring 中的 IOC
ApplicationContext 的三个常用实现类:
- ClassPathXmlApplicationContext:加载类路径下的配置文件,必须要在类路径下,否则免谈。(常用)
- FileSystemXmlApplicationContext:加载磁盘任意路径下的配置文件。
- AnnotationConfigApplicationContext:用于读取注解容器。(常用)
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); // 运行这行时已经创建了对象。
IAccountService accountService = applicationContext.getBean("accountService", IAccountService.class);
IAccountDao accountDao = applicationContext.getBean("accountDao", IAccountDao.class);
或者用 BeanFactory 实现:
Resource resource = new ClassPathResource("applicationContext.xml");
BeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader((BeanDefinitionRegistry) beanFactory);
beanDefinitionReader.loadBeanDefinitions(resource);
// 只有当创建了 Bean 之后才创建对象。
IAccountService accountService = beanFactory.getBean("accountService", IAccountService.class);
IAccountDao accountDao = beanFactory.getBean("accountDao", IAccountDao.class);
System.out.println("accountDao = " + accountDao);
System.out.println("accountService = " + accountService);
- ApplicationContext 适用于单例对象,BeanFactory 适用于多例对象。
- ApplicationContext 采用立即方式加载,BeanFactory 采用延迟方式加载。
Spring 中 Bean 的管理细节
创建 Bean 对象的三种方式
-
使用默认构造函数来创建Bean对象
如果没有默认构造函数,则无法创建Bean对象
<bean id="ClassId" class="ClassName"/> -
用某个类中的方法创建对象并存入Spring容器
<bean id="FactoryId" class="ClassName"/> <bean id="ClassId" factory-bean="FactoryBeanName" factory-method="MethodInFactory"/> -
使用类中的静态方法创建对象并存入Spring容器
<bean id="ClassId" class="FactoryName" factory-method="MethodInFactory"/>
Bean 对象的作用范围
对象默认为单例,如果要调整则更改scope参数。
<bean id="ClassId" class="ClassName" scope="singleton"/>
参数可以为:
- singleton:单例(缺省值)
- prototype:多例
- request:web请求范围
- session:web会话范围
- global-session:集群环境的会话范围 - 负载均衡状况下产生的global-session
Bean 对象的生命周期
- 单例对象
- 容器创建时对象产生
- 容器存在时对象存在
- 容器销毁时对象关闭
- 多例对象
- 使用容器获得对象时产生
- 只要没有关闭对象,对象就会存在
- Java的垃圾回收机制
Spring 的依赖注入
依赖注入:Dependency Injection
我们将依赖关系的管理都交给 Spring。而我们所需要做的就是在配置文件中说明。
三种注入数据类型:
-
基本类型和 String
直接填入value
-
其他 Bean 类型
新建 Bean 并引用
<bean id="ClassId" class="ClassName"> <constructor-arg name="BeanName" ref="BeanId"/> </bean> <bean id="BeanId" class="BeanClassName"/> -
复杂类型/集合类型
<bean id="ClassId" class="ClassName"> <property name="setName"> <set> <value>AAA</value> <value>BBB</value> <value>CCC</value> </set> </property> <property name="listName"> <list> <value>AAA</value> <value>BBB</value> <value>CCC</value> </list> </property> <!-- 除此之外还有 map array props 等等标签,其中 list set array 可以互换 map props 可以互换--> </bean>
三种注入方式:
-
使用构造函数
使用的标签:constructor-arg
其中的属性:
-
type
指定类型
-
index
指定参数索引的位置(从0开始)
-
name
指定给构造函数中指定的参数赋值 (常用)
-
value
提供基本类型或String类型的数据
-
ref
其他Bean对象的 ID,在IOC中出现过的对象都可以
-
-
使用set方法(常用)
使用的标签:property
<bean id="ClassId" class="ClassName"> <property name="[set]name" value="value"/> </bean> -
使用注解:见笔记(二)
课程链接:
https://www.bilibili.com/video/BV1Sb411s7vP?from=search&seid=11893869544331926521