1、什么是Spring
Spring是一个由Rod Johnson组织开发的一个分层的Java SE/EE 一站式轻量开源框架,它是以Ioc(控制反转)和AOP(面向切面编程)为内核,使用基本的JavaBean来完成以前只可能由EJB完成的工作,取代了EJB的臃肿,低效的开发模式。
Sping致力于JavaEE应用各层的解决方案,子啊表现层提供了SpringMVC以及与Struts框架整合的功能,在业务逻辑层可以管理事务、记录日志等;在持久层可以整合Mybatis、Hibernate、JdbcTemplete等技术。
2、Spring的优点
- 非侵入式设计
- Spring是一种非侵入式设计,它可以使应用程序对框架的依赖最小化。
- 方便解耦、简化开发
- Sping就是一个大工厂,可以将所有对象得的创建和依赖关系的维护工作都交给Spring容器来进行管理,大大降低了组件之间的耦合性。
- 支持AOP
- Spring提供了对AOP的支持,它允许将一些通用任务,如安全、事务、日志等进行集中式处理,大大提高了程序的复用性。
- 支持声明式事务处理
- 只要通过配置就可以完成对事务的管理,而无需手动编程。
- 方便程序员的测试
- Spring提供了对Junit4测试的支持,可以通过注解的方式方便的测试Spring程序。
- 降低了JavaEE API的使用难度
- Spring对JavaEE中使用难度较高的API都进行了封装,大大降低了开发难度。
3、Spring的体系结构
【图示结构】:
1、Core Container(核心容器)
- Spring核心容器是其他模块建立的基础,主要由Beans模块、Core模块、Context模块、Context-Support模块、SpEL模块组成。
- Beans模块:在此模块中提供了BeanFactory,是对工厂模式的经典实现,Spring将管理对象称为Bean。
- Core核心模块:提供了Spring框架的基本组成部分,包括Ioc和DI功能。
- Context上下文模块:建立在Beans和Core模块的基础之上,它是访问定义和配置的任何对象的媒介。
- Context-Support模块:提供第三方库嵌入Spring应用的集成支持。
- SpEL模块:是Spring3.0之后新添加的模块,他提供Spring Expression Language支持,是运行时查询和操作对象图的强大的表达式语言。
2、Date Access/Integration(数据访问/集成)
数据访问/集成层包括JDBC、ORM、OXM、JMS、和Transactions模块。
- JDBC模块:提供了一个JDBC抽象层,大幅度减少了在开发过程中对数据的操作。
- ORM模块:对流行的对象关系映射API提供了集成层支持。
- OXM模块:提供一个支持对象/XML映射的抽象层实现。
- JMS模块:指Java消息传递服务、包含使用和产生信息的特性。
- Transactions事务模块:支持对实现特殊接口以及所有的POJO类的编程和声明式事务的管理。
3、Web
Spring的We包含WebSocket、Servlet、Web和Portlet模块。
- WebSocket模块:Spring4.0以后新增的模块,它提供了WebSocket和SockJS的实现,以及对STOMP的支持。
- Servlet模块:实现了web的应用程序。
- Web模块:提供了基本的web开发集成的特性。
- Portlet模块:提供了在Portlet环境中使用MVC的实现。
4、其他模块简介
- AOP 模块提供了一个符合 AOP 联盟标准的面向切面编程的实现。
- Test 模块支持使用 JUnit 和 TestNG 对 Spring 组件进行测试。
4、Sping核心容器
Sping提供了两个核心容器,一个是BeanFactory另外一个是ApplicationContext。
1、BeanFactory
【定义位置】:
package org.springframework.beans.factory;
【类型】: 接口类型。
【作用】: 简单来说,BeanFactory就是一个管理Bean的工厂,它主要负责初始化各种Bean,并调用它们的生命周期方法。
【常见实现类】:
- XmlBeanFactory:该类会根据XML配置文件中的定义来装配Bean。
2、ApplicationContext
ApplicationContext是BeanFactory的子接口,也被称为应用上下文,是另外一种常用的Sping核心容器。
【定义位置】:
package org.springframework.context;
【类型】: 接口类型。
【作用】: 包含了BeanFactory的所有功能,同时还支持对国际化、资源访问、事件传播等方面的支持。
1、通过ClassPathXmlApplicationContext创建
ClassPathXmlApplicationContext会从类路径classPath中寻找指定的XML配置文件,找到并装载完成ApplicationContext的实例化工作。
- 语法:
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("配置文件名称和位置")
2、通过FileSystemXmlApplicationContext 创建
此时的路径不再是从类路径开始查找,而是通过参数指定配置文件的位置,如果参数使用的不是绝对路径,方法在调用的时候会默认使用绝对路径。(不推荐使用)。
- 语法:
FileSystemXmlApplicationContext applicationContext=new FileSystemXmlApplicationContext("配置文件名称和位置");
3、获取对象的两种基本方式
- Object getBean(String name):根据容器中Bean的id或者name来获取指定的Bean,获取之后要进行强制类型转换。
- T getBean(Class requeryType):根据类的类型来获取Bean的实例,获取之后不需要进行类型转换。
3、BeanFactory和ApplicationContext的区别
- 都是通过XML配置文件的方式加载Bean。
- 当Bean的某一个属性没有注入的时候,使用BeanFactory加载后,在第一次调用getBean()方法的时候就会抛出异常。而ApplicationContext则是在初始化自检的时候就会报出异常。
- 推荐使用ApplicationContext。
5、Spring入门案例之HelloWorld
1、创建maven项目添加如下依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
</dependencies>
2、创建一个类
package cn.simplelife.domain;
/**
* @ClassName Person
* @Description
* @Author simplelife
* @Date 2022/11/17 22:46
* @Version 1.0
*/
public class Person {
private Long id;
private String name;
public Person(Long id, String name) {
this.id = id;
this.name = name;
}
public Person() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public void work() {
System.out.println("疯狂写代码");
}
}
3、编写配置文件让容器创建对象
<?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">
<!--使用spring创建对象
id:名称一般采用类名的首字母小写
class:要创建对象的全限定类名
property:属性
name:对象的属性名称
value:想要赋值的值
创建完成之后会将其存放在ioc容器中
-->
<bean id="person" class="cn.simplelife.domain.Person">
<property name="id" value="1"/>
<property name="name" value="李四"/>
</bean>
</beans>
4、编写测试类获取对象
import cn.simplelife.domain.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ClassName PersonTest
* @Description
* @Author simplelife
* @Date 2022/11/17 22:49
* @Version 1.0
*/
public class PersonTest {
@Test
public void testPersonBySpring() {
// 1、根据配置文件启动spring容器
// 2、对象是在容器启动的时候创建的
// 3、在容器启动的时候创建的好处:
// 1、提高用户体验度
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("_01helloworld.xml");
// 2、从容器中获取对象
Person person = (Person) applicationContext.getBean("person");
// 3、使用对象
person.work();
}
}
6、依赖注入
1、什么是依赖注入
依赖注入简称DI与控制反转Ioc描述的是同一种含义,只不过是角度不同。
当某个Java对象(调用者)需要调用另外一个Java对象(被调用者)的时,在以前的写法中,需要我们手动的去在调用者的类中new被调用者的对象来创建被调用者对象。这样的方式导致调用者和被调用者之间的耦合度增高,不利于项目的维护和升级。
在Spring被广泛使用之后,对象实例的调用不需要调用者通过new的方式创建,而是将这部分工作交给spring容器来进行创建,并且spring容器会负责控制调用者与被调用者之间的关系,不再像之前一样由调用者去控制程序之间的关系。
2、依赖注入的实现方式
1、setter方法注入
- Spring使用setter方法注入被依赖的实例对象。通过调用无参构造器或无参静态工厂实例化Bean对象之后,调用该Bean的Setter方法,就可以实现基于setter方法的注入。
- 代码演示
package cn.simplelife.dao.impl;
import cn.simplelife.dao.StudentDAO;
import lombok.Cleanup;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* @ClassName StudentDAOImpl
* @Description
* @Author simplelife
* @Date 2022/11/21 11:21
* @Version 1.0
*/
public class StudentDAOImpl implements StudentDAO {
private DataSource dataSource;
// 提供set方法,在配置文件中进行注入
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public void save(String name, String password) throws SQLException {
@Cleanup
Connection connection = dataSource.getConnection();
@Cleanup
PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO student(name,password)VALUES (?,?)");
preparedStatement.setString(1, name);
preparedStatement.setString(2, password);
preparedStatement.executeUpdate();
}
}
- 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--关联db.properties-->
<context:property-placeholder location="classpath:db.properties"/>
<!--配置数据库连接池-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${password}"/>
</bean>
<!--配置StudentDAOImpl-->
<bean id="studentDAO" class="cn.simplelife.dao.impl.StudentDAOImpl">
<!--此时注入连接池对象-->
<property name="dataSource" ref="druidDataSource"/>
</bean>