Spring框架是一款轻量级的开发框架,有两大核心思想:IOC(控制反转)和AOP(面向切面编程)。目的:为了符合企业级标准:高内聚、低耦合,且简化第三方JavaEE中间件技术的使用。Spring框架包括:IOC容器、Validation数据校验、AOP面向切面编程、Transcations事务管理、Spring JDBC、Spring MVC框架、以及各类第三方JavaEE中间件技术集成。
一、基本概念
1、Bean
代表被IOC容器管理的对象(就是类),通过配置文件告诉IOC容器帮助我们管理哪些bean对象。
2、Spring IOC的理解
IOC(控制反转)是Spring两大核心思想之一,作用:解决业务逻辑和其他各层之间松耦合问题。区别于传统意义上,通过new的方式创建,而是将创建对象的过程交给Spring进行管理。Spring框架使用配置文件的方式,创建bean对象并管理各个bean之间的依赖关系,最终实现解耦。
3、Spring IOC容器的理解
IOC容器其实就是一个Map集合,key是每一个bean对象的ID,value是bean对象本身,默认使用单例的方式将bean存储在Map中;使用集合存储BeanDefinition对象,该对象的封装了Spring对一个Bean所有的配置信息;IOC容器属于Spring core模块,用来创建和管理bean,IOC容器通过配置文件中配置的数据,对各个bean对象进行实例化,并根据bean对象之间的依赖关系完成bean之间的注入。
4、Spring DI的理解
DI(依赖注入),在容器创建好对象后,处理各个对象之间的依赖关系,在IOC容器运行时,给当前对象注入它所需要的另一个对象。例如:控制层在运行时可能需要业务层的支持,就不再像传统意义上在控制层new一个业务层对象,而是在配置文件中给控制层注入一个它所需要的业务层对象,实现控制层和业务层之间解耦。
二、Spring快速入门(创建Student对象)
1、创建Spring项目,在pom.xml中加入Spring依赖。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.26</version>
</dependency>
2、创建Student类。
public class Student {
}
3、在resources目录下创建配置文件。
所有的配置标签写在<beans></beans>这一对父标签中。
子标签为<bean></bean>,属性有:
id:唯一标识
class:类的完全限定名称(注入的bean对象的包名)
<?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">
<!--注入Student类-->
<bean id="student" class="spring.ioc.popj.Student"></bean>
</beans>
4、在测试方法中创建出Student对象
容器对象有2个:BeanFactory(父接口),ApplicationContext(子接口)
容器对象的实现类有3个:
ClassPathXmlApplicationContext==>通过文件的相对路径获取核心对象(实现类)
FileSystemXmlApplicationContext==>通过文件的绝对路径获取核心对象(实现类)
AnnotationConfigApplicationContext==>通过加载配置类获取核心对象(实现类)
public class Test01 {
public static void main(String[] args) {
//1.加载spring主配置文件获取容器对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
//2.向spring容器获取student实例
Student student = (Student) applicationContext.getBean("student");
System.out.println(student);
}
}
三、Spring DI(依赖注入)的实现方式
1、set注入:通过set方法维护对象之间的依赖关系。
注入的数据类型为:注入对象。
例:三层之间的调用
控制层:
public class IUserControllerImpl implements IUserController{
//定义业务层对象
private IUserService service;
//setter()
public void setService(IUserService service) {
this.service = service;
}
@Override
public void save() {
System.out.println("---controller控制层---");
//调业务层的save()
service.save();
}
}
业务层:
public class IUserServiceImpl implements IUserService{
//定义数据访问层对象
private IUserDao dao;
//setter()
public void setDao(IUserDao dao) {
this.dao = dao;
}
@Override
public void save() {
System.out.println("---service业务层---");
//调数据访问层的save()
dao.save();
}
}
数据访问层:
public class IUserDaoImpl implements IUserDao {
@Override
public void save() {
System.out.println("---dao层数据访问---");
}
}
配置文件:
在bean标签内部开启配置,
配置位置:<bean>此位置</bean>
配置语法:<property 属性名="属性值"></property>
配置属性:name:属性名称,value:属性值,ref:属性值的引用。
<?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">
<!-- 注入方式:set注入对象 -->
<!-- 注入IUserControllerImpl -->
<bean id="controllerImpl" class="IUserControllerImpl">
<property name="service" ref="serviceImpl"></property>
</bean>
<!-- 注入IUserServiceImpl -->
<bean id="serviceImpl" class="IUserServiceImpl">
<property name="dao" ref="daoImpl"></property>
</bean>
<!-- 注入IUserDaoImpl -->
<bean id="daoImpl" class="IUserDaoImpl"></bean>
</beans>
测试类:
public class Test01 {
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("applicationContext.xml");
//set注入对象
IUserController iUserController = (IUserController) beanFactory.getBean("controllerImpl");
//控制层调save()方法
iUserController.save();
}
}
注入的数据类型为:注入基本数据类型和String。
定义Student类:不通过有参构造方法给属性赋值,而是在IOC容器创建对象时通过set()给属性赋值。
public class Student {
//成员变量
private String name;
private String hooby;
private int age;
//setter()
public void setName(String name) {
this.name = name;
}
public void setHooby(String hooby) {
this.hooby = hooby;
}
public void setAge(int age) {
this.age = age;
}
//toString()
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", hooby='" + hooby + '\'' +
", age=" + age +
'}';
}
}
配置文件:
<?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">
<!-- set注入基本数据类型和String -->
<bean id="student" class="spring.ioc.popj.Student">
<property name="name" value="光头强"></property>
<property name="hooby" value="砍树"></property>
<property name="age" value="25"></property>
</bean>
</beans>
注入复杂类型(list、array、set、map、properties)。
Teacher类:属性类型类复杂类型
public class Teacher {
//List
private List list;
//Set
private Set set;
//Map
private Map map;
//array
private String[] array;
//properties
private Properties properties;
public void setList(List list) {
this.list = list;
}
public void setSet(Set set) {
this.set = set;
}
public void setMap(Map map) {
this.map = map;
}
public void setArray(String[] array) {
this.array = array;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "Teacher{" +
"list=" + list +
", set=" + set +
", map=" + map +
", array=" + Arrays.toString(array) +
", properties=" + properties +
'}';
}
}
配置文件:
<?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">
<!-- set注入复杂类型(list,set,map,array,properties) -->
<bean id="teacher" class="spring.ioc.popj.Teacher">
<!-- list类型 -->
<property name="list">
<list>
<value>上课</value>
<value>备课</value>
<value>批作业</value>
</list>
</property>
<!-- set类型 -->
<property name="set">
<set>
<value>健身</value>
<value>跑步</value>
<value>散步</value>
</set>
</property>
<!-- array类型 -->
<property name="array">
<array>
<value>光头强</value>
<value>熊大</value>
<value>熊二</value>
</array>
</property>
<!-- map类型:键值对 -->
<property name="map">
<map>
<entry key="千里送鹅毛" value="礼轻情意重"></entry>
<entry key="小葱拌豆腐" value="一清二白"></entry>
<entry key="及时雨" value="宋江"></entry>
</map>
</property>
<!-- properties类型 -->
<property name="properties">
<props>
<prop key="自助">12</prop>
<prop key="面条">13</prop>
<prop key="肉夹馍">14</prop>
</props>
</property>
</bean>
</beans>
2、构造注入:通过构造方法维护对象之间的依赖关系。
注入的数据类型为:注入对象。l
例:三层之间的调用
控制层:
public class IUserControllerImpl implements IUserController{
//定义业务层对象
private IUserService service;
//有参构造方法(传入参数:IUserService)
public IUserControllerImpl(IUserService service) {
this.service = service;
}
//无参构造方法
public IUserControllerImpl() {
}
@Override
public void save() {
System.out.println("---controller控制层---");
//调业务层save()
service.save();
}
}
业务层:
public class IUserServiceImpl implements IUserService{
//定义数据访问层对象
private IUserDao dao;
//无参构造方法
public IUserServiceImpl() {
}
//有参构造方法
public IUserServiceImpl(IUserDao dao) {
this.dao = dao;
}
@Override
public void save() {
System.out.println("---service业务层---");
//调数据访问层save()
dao.save();
}
}
数据访问层:
public class IUserDaoImpl implements IUserDao {
@Override
public void save() {
System.out.println("---dao层数据访问---");
}
}
配置文件:
在bean标签内部开启配置
配置位置:<bean>此位置</bean>
配置语法:< constructor-arg 属性名="属性值"></ constructor-arg>
配置属性:name:构造方法中参数名称,value:属性值,ref:属性值的引用,index:构造 方法中参数下标,type:构造方法中参数类型。
<?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">
<!--构造注入:注入对象 -->
<!-- name:构造方法中参数名称 ref:属性值的引用 -->
<bean id="controllerImpl" class="spring.ioc.controller.IUserControllerImpl">
<constructor-arg name="service" ref="serviceImpl"></constructor-arg>
</bean>
<bean id="serviceImpl" class="spring.ioc.service.IUserServiceImpl">
<constructor-arg name="dao" ref="daoImpl"></constructor-arg>
</bean>
<bean id="daoImpl" class="spring.ioc.dao.IUserDaoImpl"></bean>
</beans>
注入的数据类型为:注入基本数据类型和String。
Student类:通过有参构造方法在创建对象时给定属性值。
public class Student {
private String name;
private int age;
//有参构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
配置文件:
<?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">
<!-- 构造注入Student类,注入基本数据类型和String:使用构造方法的参数名称 -->
<bean id="student1" class="spring.ioc.popj.Student">
<constructor-arg value="光头强" name="name"></constructor-arg>
<constructor-arg value="20" name="age"></constructor-arg>
</bean>
<!-- 构造注入Student类,注入基本数据类型和String:使用构造方法的参数下标 -->
<bean id="student2" class="spring.ioc.popj.Student">
<constructor-arg value="熊大" index="0"></constructor-arg>
<constructor-arg value="18" index="1"></constructor-arg>
</bean>
<!-- 构造注入Student类,注入基本数据类型和String:使用构造方法的参数类型 -->
<bean id="student3" class="spring.ioc.popj.Student">
<constructor-arg value="熊二" type="java.lang.String"></constructor-arg>
<constructor-arg value="16" type="int"></constructor-arg>
</bean>
</beans>
构造注入不支持数据类型为复杂类型。
3、属性注入(不推荐):使用成员变量注入bean,原因:使用私有的成员变量,依靠反射实现,破坏封装,只能依靠IOC容器实现注入,不严谨。
四、Bean的实例化
1、通过类的无参构造方法实例化(默认方式)
例:创建Teacher对象
Teacher类:
通过类的无参构造方法实例化(默认)
public class Teacher {
public Teacher() {
System.out.println("---Teacher类的无参构造方法---");
}
}
配置文件:
<?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">
<!-- 通过类的无参构造方法实例化(默认) -->
<bean id="teacher" class="spring.ioc.popj.Teacher"></bean>
</beans>
2、通过指定工厂创建对象
Teacher类:
public class Teacher{
}
Factory类:
public class BeansFactory {
//通过工厂创建Teacher对象
public Teacher createStu() {
System.out.println("===通过工厂创建对象===");
return new Teacher();
}
}
配置文件:
<?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">
<!-- 通过指定工厂创建对象 -->
<!--factory-bean:指定工厂类,factory-method:指定工厂类中创建对象的方法-->
<bean id="teacher" class="spring.ioc.popj.Teacher" factory-bean="factory" factory-method="createStu"></bean>
<bean id="factory" class="spring.ioc.factory.BeasFactory"></bean>
</beans>
3、通过指定静态工厂创建对象
Teacher类:
public class Teacher{
}
Factory类:
public class StaticBeansFactory {
//通过工厂创建Teacher对象
public static Teacher createStu() {
System.out.println("===通过静态工厂创建对象===");
return new Teacher();
}
}
配置文件:
<?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">
<!-- 通过指定静态工厂创建对象 -->
<bean id="teacher" class="spring.ioc.factory.StaticBeasFactory" factory-method="createStu"></bean>
</beans>
五、Bean的作用域
语法:scope="属性"
singleton(单例):Spring只会为该bean对象创建唯一实例,Spring中的bean默认都是单例。
prototype(多例):每次获取bean,Spring都会创建一个新的bean实例。
request:每一次http请求,Spring都会创建一个新的实例。
session:不同的http会话,Spring都会创建一个新的实例。
request和session需要有Web环境。
<?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">
<!-- 对象的作用域 -->
<!--单例,性能好,安全性差-->
<bean id="teacher" class="spring.ioc.popj.Teacher" scope="singleton"></bean>
<!-- 多例,性能差,安全性好 -->
<bean id="teacher" class="spring.ioc.popj.Teacher" scope="prototype"></bean>
</beans>