文章目录
一、Spring IoC
Spring IoC 容器组件,可以完成对象的创建、对象属性赋值、对象管理
1.1 Spring框架部署(IoC)
1.1.1 创建Maven工程
- Java
- Web
1.1.2 添加SpringIoC依赖
- core
- beans
- aop
- expression
- context
在Maven中由于context依赖于其他包,所以导入context后,其他依赖会自动导入
<!--
导入jar包就是添加项目依赖 dependencies
-->
<dependencies>
<!--
写入添加的jar包
-->
<!--
spring 的core包
https://mvnrepository.com/artifact/org.springframework/spring-core
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.16.RELEASE</version>
</dependency> -->
<!--
spring 的bean的包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.16.RELEASE</version>
</dependency>-->
<!--
spring 的context的包(只需要这一个包就可以了)
-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.16.RELEASE</version>
</dependency>
</dependencies>
1.1.3 创建Spring配置文件
通过配置文件"告诉"Spring容器创建什么对象,给对象属性赋什么值
在resources目录下创建名为 appicationContext.xml 的文件(文件名是可以自定义的)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 对于一个xml文件如果作为框架的配置文件,需要遵守框架的配置规则 -->
<!-- 通常一个框架为了让开发者能够正确的配置,都会提供xml的规范文件(dtd\xsd) -->
</beans>
1.2 SpringIoC使用
使用 SpringIoC组件创建并管理对象
1.2.1 创建一个实体类
public class Student {
int sId;
String sName;
String sex;
int age;
String major;
Date birthday;
}
1.2.2 在Spring配置文件中配置实体类
<?xml version="1.0" encoding="UTF-8"?>
<!--suppress ALL -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
bean:spring容器创建一个对象
1. id 创建对象的名字 一般是类名的首字母小写
2. class 创建什么类型对象 类名+对象名
-->
<!--suppress SpringFacetInspection -->
<bean id="student" class="com.sxy.entity.Student">
<!--
通过property标签给属性赋值
-->
<property name="sId" value="1002"/>
<property name="sName" value="李四"/>
<property name="major" value="计算机"/>
<property name="sex" value="男"/>
<property name="age" value="18"/>
<!--
birthday是什么类型?
Date birthday; 是java.util.Data 对象类型
ref:references的缩写,是引用的意思。 引用容器里面的一个对象;
方式1:
<property name="birthday" ref="date"></property>
<bean id="date" class="java.util.Date"></bean>
方式2:
<property name="birthday">
<bean class="java.util.Date"></bean>
</property>
-->
<property name="birthday">
<bean class="java.util.Date"></bean>
</property>
</bean>
<!--
让spring帮我们创建一个date对象
<bean id="date" class="java.util.Date"></bean> -->
</beans>
1.2.3 初始化Spring对象工厂,获取对象
ClassPathXMLApplicationContext
// 加载配置文件 得到spring的上下文对象
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取对象,通过getBean("bean标签里面的id属性值")方法
Student student = (Student) context.getBean("student");//返回的是object对象
System.out.println(student);
1.3 IoC和DI
- IoC (Inverse of Control) 控制反转,通过Spring对象工厂完成对象的创建
- DI (Dependency Injection)依赖注入,在Spring完成对象创建的同时依赖Spring容器完成对象属性的赋值
1.3.1 IoC
当我们需要通过Spring对象工厂创建某个类的对象时候,需要将这个交给Spring管理——通过
bean标签配置
<!--通过bean将实体类配置给Spring进行管理,id表示实体类的唯一表示-->
<bean id="stu" class="com.sxy.entity.Student"></bean>
1.3.2 DI
通过Spring容器给创建的对象属性赋值
<bean id="clazz" class="com.sxy.entity.Clazz"></bean>
<!--通过bean将实体类配置给Spring进行管理,id表示实体类的唯一表示-->
<bean id="stu" class="com.sxy.entity.Student" autowire="byName">
<property name="stuNum" value="10001"/>
</bean>
1.4 DI依赖注入
1.4.1 依赖注入三种方式
Spring容器加载配置文件之后,通过反射创建类的对象,并给属性赋值;
Spring容器通过反射实现属性注入有三种方式:
- set方法注入
- 构造器注入
- 接口注入(不常用)
1.4.2 set方法注入
在bean标签中通过配置property标签给属性属性赋值,实际上就是通过反射调用set方法完成属性的注入
简单类型及字符串
直接通过property标签的value属性赋值
<!--通过bean将实体类配置给Spring进行管理,id表示实体类的唯一表示-->
<bean id="stu" class="com.cg.ioc.bean.Student" autowire="byName">
<!-- 简单类型 -->
<property name="stuNum" value="10001"/>
<property name="stuAge" value="12"/>
<!-- 字符串类型-->
<property name="sName" value="abcd"/>
</bean>
日期类型
方式1:在property标签中通过ref引用Spring容器中的一个对象
<!--创建一个java.util.Date的bean,再通过ref引入-->
<bean id="date" class="java.util.Date"></bean>
<bean id="stu" class="com.cg.ioc.bean.Student" >
<!-- 日期类型-->
<property name="enterenceTime" ref="date"/>
</bean>
方式2:在property标签中添加子标签bean来指定对象
<bean id="stu" class="com.cg.ioc.bean.Student" >
<!-- 日期类型-->
<!--直接在property中创建一个java.util.Date的bean-->
<property name="enterenceTime">
<bean class="java.util.Date"/>
</property>
</bean>
自定义类对象属性
方式1:在property标签中通过ref引用Spring容器中的一个对象(与时间类型一致)
<bean id="cla" class="com.cg.ioc.bean.Clazz">
<!--com.cg.ioc.bean.Clazz对象中的数据-->
<property name="classId" value="2010"/>
<property name="className" value="Java2010"/>
</bean>
<bean id="stu" class="com.cg.ioc.bean.Student">
<!-- 自定义对象类型-->
<property name="clazz" ref="cla"/>
</bean>
方式2:在property标签中添加子标签bean来指定对象(与时间类型一致)
<bean id="stu" class="com.cg.ioc.bean.Student">
<!-- 自定义对象类型-->
<property name="clazz">
<bean class="com.cg.ioc.bean.Clazz">
<!--com.cg.ioc.bean.Clazz对象中的数据-->
<property name="classId" value="2010"/>
<property name="className" value="Java2010"/>
</bean>
</property>
</bean>
集合类型
-
List
- List List中的元素是字符串或者简单类型的封装类
方法一:写在一个value中用逗号隔开
方式二:用list标签列举<property name="hobbies" value="旅游,电影"/>
<property name="hobbies" > <list> <value>旅游</value> <value>电影</value> <value>Java</value> </list> </property>
- List List中的元素是对象类型
方式1:通过ref引用Spring容器中的一个对象
方式2:在property标签中添加子标签bean来指定对象<property name="hobbies" > <list> <ref bean="book"></ref> <!--引用容器中的备案--> <ref bean="book"></ref> </list> </property>
<property name="hobbies" > <list> <bean class="com.cg.ioc.bean.Book"/> <bean class="com.cg.ioc.bean.Book"/> <bean class="com.cg.ioc.bean.Book"/> <bean class="com.cg.ioc.bean.Book"/> </list> </property>
- List List中的元素是字符串或者简单类型的封装类
-
Set
set和list元素注入方式相同<property name="sets"> <set> <!--和list元素注入方式相同--> </set> </property>
-
Map
<property name="maps"> <map> <!--map是由一组key和value组成的entry--> <entry> <key> <!--key的值--> <value>k1</value> </key> <!--value的值--> <value>123</value> </entry> <entry> <key> <value>k2</value> </key> <value>456</value> </entry> </map> </property>
-
Properties
<property name="properties"> <props> <prop key="k1">aaa</prop> <prop key="k2">bbb</prop> </props> </property>
1.4.3 构造器注入
bean对象
public class Student {
private String stuNum;
private String stuName;
private String stuGender;
private int stuAge;
private double weight;
private Date enterenceTime; //入学日期
//集合类型属性
private Clazz clazz;
public Student(String stuNum, String stuName, String stuGender, int stuAge, double weight, Date enterenceTime, Clazz clazz) {
this.stuNum = stuNum;
this.stuName = stuName;
this.stuGender = stuGender;
this.stuAge = stuAge;
this.weight = weight;
this.enterenceTime = enterenceTime;
this.clazz = clazz;
}
}
简单类型、字符串、对象
<bean id="date" class="java.util.Date"></bean>
<bean id="stu" class="com.cg.ioc.bean.Student">
<!--index 对应构造器参数位置的索引,可不写,如不写则按上下顺序对应-->
<constructor-arg index="0" value="10001"/> <!--字符串类型-->
<constructor-arg index="2" value="女"/>
<constructor-arg index="1" value="张三"/>
<constructor-arg index="3" value="21"/> <!--简单类型-->
<constructor-arg index="4" value="62.5"/>
<constructor-arg index="5" ref="date"/> <!--对象类型-->
<constructor-arg index="6"> <!--对象类型-->
<bean class="com.cg.ioc.bean.Clazz"></bean>
</constructor-arg>
</bean>
集合类型属性
<bean id="stu1" class="com.cg.ioc.bean.Student">
<!--list类型-->
<constructor-arg index="0">
<list>
<value>11</value>
<value>22</value>
<value>33</value>
</list>
</constructor-arg>
<!--set类型-->
<constructor-arg index="1">
<set>
<value>aa</value>
<value>bb</value>
<value>cc</value>
</set>
</constructor-arg>
<!--map类型-->
<constructor-arg index="2">
<map>
<entry>
<key><value>key1</value></key>
<value>value1</value>
</entry>
<entry>
<key><value>key2</value></key>
<value>value2</value>
</entry>
</map>
</constructor-arg>
<!--Properties类型-->
<constructor-arg index="3">
<props>
<prop key="k1">v1</prop>
<prop key="k2">v2</prop>
</props>
</constructor-arg>
</bean>
1.5 Bean的作用域
在bean标签可以通过scope属性指定对象的的作用域
-
scope=“singleton” 表示当前bean是单例模式(默认饿汉模式,Spring容器初始化阶段就会
完成此对象的创建;当在bean标签中设置 lazy-init="true"变为懒汉模式)<!--多个getBean获取的是同一对象--> <bean id="book" class="com.cg.ioc.bean.Book" scope="singleton" lazy-init="true"> </bean>
-
scope=“prototype” 表示当前bean为非单例模式,每次通过Spring容器获取此bean的对象时
都会创建一个新的对象<!--每次getBean获取的都是新的对象--> <bean id="book" class="com.cg.ioc.bean.Book" scope="prototype"></bean>
1.6 Bean的生命周期
简化版本 :
在bean标签中通过init-method属性指定当前bean的初始化方法,初始化方法在构造器执行之后执行,通过destroy-method属性指定当前bean的销毁方法,销毁方法在对象销毁之前执行–>
Bean类
public class Book {
private int bookId;
private String bookName;
//初始化方法:在创建当前类对象时调用的方法,进行一些资源准备工作
public void init(){
System.out.println("-------init");
}
//销毁方法:在Spring容器销毁对象时调用此方法,进行一些资源回收性的操作
public void destory(){
System.out.println("-------destory");
}
}
Spring配置文件
<bean id="book" class="com.cg.ioc.bean.Book" scope="prototype"initmethod="init"
destroy-method="destory" ></bean>
相对完整 :
- 实例化:Spring对Bean进行实例化(默认调用无参构造器),scope为
singleton
- 属性赋值:容器对属性进行注入
- 如果Bean实现了
BeanNameAware
接口,容器就将Bean的Id通过setBeanName
方法传进来 - 如果Bean实现了
BeanFactory
接口,容器就将BeanFactory容器实例通过setBeanFactory
传入 - 如果Bean实现了
ApplicationContextAware
接口,那么容器将Bean所在的 应用上下文 引用传入 - 如果Bean实现了
BeanPostProcessor
接口,那么就调用postProcessBeforeInitialization
方法对Bean进行前置处理 - 如果Bean实现了
InitializingBean
接口,那就通过调用afterPropertiesSet
方法进行 自定义的初始化 ,作用等同于,为Bean设置init-method
属性 - 如果Bean实现了
BeanPostProcessor
接口,那么就调用postProcessAfterInitialization
方法对Bean进行后置处理 - 如果Bean实现了
DisposableBean
接口,那就通过调用destroy
方法进行 自定义的销毁 等同于为
Bean设置destroy-method
属性
<bean id="fierceMan" class="com.softeem.entity.FierceMan"
scope="singleton" init-method="customInit" destroy-method="customDestroy">
<!-- 背心,短裤,人字拖 -->
<property name="clothes">
<set>
<value>背心</value>
<value>短裤</value>
<value>人字拖</value>
</set>
</property>
</bean>
public class FierceMan implements BeanFactoryAware, InitializingBean, DisposableBean {
private BeanFactory factory;
/**
* 猛男喜欢穿的衣服
*/
private Set<String> clothes;
/**
* 猛男喜欢的电脑
*/
private List<Computer> computerList;
/**
* 猛男喜欢看的卡通
*/
private Map<String,Object> cartoonMap;
/**
* 猛男存小姐姐的数据库信息
*/
private Properties properties;
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public Map<String, Object> getCartoonMap() {
return cartoonMap;
}
public void setCartoonMap(Map<String, Object> cartoonMap) {
this.cartoonMap = cartoonMap;
}
public List<Computer> getComputerList() {
return computerList;
}
public void setComputerList(List<Computer> computerList) {
this.computerList = computerList;
}
public Set<String> getClothes() {
return clothes;
}
public void setClothes(Set<String> clothes) {
System.out.println("通过set方法注入clothes");
this.clothes = clothes;
}
public FierceMan() {
System.out.println("猛男被无参构造了");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
factory = beanFactory;
}
@Override
public void destroy() throws Exception {
System.out.println("实现了DisposableBean的自定义销毁的方法");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("实现了InitializingBean的初始化方法");
}
public void customInit(){
System.out.println("init-method定义的方法");
}
public void customDestroy(){
System.out.println("destroy-method定义的方法");
}
1.7 自动装配
自动装配:Spring在实例化当前bean的时候从Spring容器中找到匹配的实例赋值给当前bean的属
性
自动装配策略有两种:
-
byName 根据当前Bean的属性名在Spring容器中寻找匹配的对象 ,如果根据name找打了
bean但是类型不匹配则抛出异常<bean id="clazz" class="com.cg.ioc.bean.Clazz"></bean> <!--com.cg.ioc.bean.Student中包含com.cg.ioc.bean.Clazz对象,自动装配时根据name:Clazz寻找匹配的对象--> <bean id="stu2" class="com.cg.ioc.bean.Student" autowire="byName"></bean>
-
byType 根据当前Bean的属性类型在Spring容器中寻找匹配的对象,如果根据类型找到了多
个bean也会抛出异常<bean id="clazz2" class="com.cg.ioc.bean.Clazz"></bean> <!--com.cg.ioc.bean.Student中包含com.cg.ioc.bean.Clazz对象,自动装配时根据class:Clazz寻找匹配的对象--> <bean id="stu2" class="com.cg.ioc.bean.Student" autowire="byType"></bean>