深入学习Spring框架(一)- 入门

时间:2023-12-17 22:27:20

1.Spring是什么?

  Spring是一个JavaEE轻量级的一站式开发框架。
    JavaEE: 就是用于开发B/S的程序。(企业级)
    轻量级:使用最少代码启动框架,然后根据你的需求选择,选择你喜欢的模块使用。
    重量级:早期有的EJB,开发一个HelloWorld程序都需要引入EBJ的全部模块
    一站式:Spring框架提供涵盖了JavaEE开发的表示层,服务层,持久层的所有组件功能。也就是说,原则上,学完一套Spring框架,不用其他框架就可以完成网站一条流程的开发。但是Spring仍然可以和其他的框架无缝整合。

2.Spring的优点

  轻量:Spring 是轻量的,就是除内核模块(4个jar),其他模块由开发者*选择使用,同时支持整合其他框架。也可以称为就是可插拔式开发框架,像插头和插座一样,插上就用。这就是Spring框架核心理念(Ioc)。
  控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们。
  面向切面的编程(AOP):Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
  容器:Spring 包含并管理应用中对象的生命周期和配置。
  MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。
  事务管理:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)。
  异常处理:Spring 提供方便的API把具体技术相关的异常(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked 异常。

3.Spring的作用

  Spring强调的理念是,轻量级。Spring的轻量级主要体现在模块的可插拔,Spring提供的功能模块,除了内核模块以外,开发人员可以选择性使用。所以,Spring框架在现实开发中,主要的功能用于整合各种开发框架开发项目。

4.Spring框架包

  Spring官方网站:https://spring.io/

  4.1 下载

  Spring官方提供的Maven方式的项目下载:https://start.spring.io/
  但是基于简单入门的原则,我们要通过导入包的方式来学习。需要下载框架的zip包
  地址为:http://repo.springsource.org/libs-release-local/org/springframework/spring/

  4.2 目录说明

  根目录:

  深入学习Spring框架(一)- 入门

  jar包:

  深入学习Spring框架(一)- 入门

  包说明:

包名 说明
spring-aop-4.3.2.RELEASE.jar 实现了AOP的支持
spring-aspects-4.3.2.RELEASE.jar AOP框架aspects支持包
spring-beans-4.3.2.RELEASE.jar 内核支撑包,实现了处理基于xml对象存取
spring-context-4.3.2.RELEASE.jar  内核支撑包,实现了Spring对象容器
spring-context-support-4.3.2.RELEASE.jar  容器操作扩展包,扩展了一些常用的容器对象的设置功能
spring-core-4.3.2.RELEASE.jar  内核支撑包,Spring的内核
spring-expression-4.3.2.RELEASE.jar  内核支撑包,实现了xml对Spring表达式的支持
spring-instrument-4.3.2.RELEASE.jar  提供了一些类加载的的工具类
spring-instrument-tomcat-4.3.2.RELEASE.jar  提供了一些tomcat类加载的的工具类,实现对应Tomcat服务的调用
spring-jdbc-4.3.2.RELEASE.jar  SpringJDBC实现包,一个操作数据库持久层的子框架
spring-jms-4.3.2.RELEASE.jar  集成jms的支持,jms:Java消息服务。
spring-messaging-4.3.2.RELEASE.jar  集成messaging api和消息协议提供支持
spring-orm-4.3.2.RELEASE.jar  ORM框架集成包,实现了Hibernate,IBatis,JDO的集成。
spring-oxm-4.3.2.RELEASE.jar  Spring OXM对主流O/X Mapping框架做了一个统一的抽象和封装。就是对应XML读写框架的支持
spring-test-4.3.2.RELEASE.jar  Spring集成JUnit测试
spring-tx-4.3.2.RELEASE.jar  事务代理的支持
spring-web-4.3.2.RELEASE.jar  SpringWeb通用模块
spring-webmvc-4.3.2.RELEASE.jar  SpringMVC子框架
spring-webmvc-portlet-4.3.2.RELEASE.jar  Spring对门户技术(portlet)的支持
spring-websocket-4.3.2.RELEASE.jar  Spring对websocket的支持

注:红色部分为基础核心包,使用Spring必须导入

5.入门实例

  Spring之所以可以实现模块的可插拔是支持依赖注入,所谓的依赖注入/控制反转就是不用new就可以创建对象。

  使用Spring框架不用new创建一个对象:

  1.创建项目并导入jar包:将Spring的基础支撑包和依赖的日志包复制到lib文件下,并且加入项目中

  深入学习Spring框架(一)- 入门

  2.创建配置文件
  在项目的src下面创建配置文件applicationContext.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"> </beans>

  3.创建对象到Spring容器中
  创建一个类

package com.gjs.service;

public class HelloSpringService {
public void say() {
System.out.println("你好!Spring");
}
}

  往applicationContext.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">
<!-- <bean id="" class = "">
配置让spring管理类的对象的创建
id : 唯一标识
class :被管理类的全限定名
-->
<bean id="HelloSpringService" class="com.gjs.service.HelloSpringService"/> </beans>

  测试类, 使用getBean方法获得容器中的对象。

package com.gjs.test;

import static org.junit.Assert.*;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.gjs.service.HelloSpringService; public class TestSpring {
@Test
public void testName() throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
HelloSpringService helloSpringService = context.getBean("HelloSpringService",HelloSpringService.class);
helloSpringService.say();
}
}

6.Spring容器的两个实现

ClassPathXmlApplicationContext:通过classpath路径(相对路径)直接获得加载的xml文件(推荐使用)

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

FileSystemXmlApplicationContext:通过文件路径(绝对路径)来获得加载的xml文件。

ApplicationContext context = new FileSystemXmlApplicationContext("D:\\java\\eclipse-workspace\\spring1\\src\\applicationContext.xml");

8.控制反转(IOC)和依赖注入(DI)(A)

  DI:Dependency Injection(依赖注入):

  依赖注入是指Spring创建对象的过程中,将对象依赖属性(简单值,集合,对象)通过配置设值给该对象。

  IoC:Inverse of Control(控制反转):

  Spring号称是一个可以实现模块可插拔的JavaEE开发框架。而实现程序可插拔的核心理念就是控制反转。所谓的控制反转,就是将代码的调用权从调用方转移给被调用方(服务提供方)。不用修改调用方的的代码,只要修改配置文件就实现对象的切换。
  读作“反转控制”,更好理解,它不是什么技术,而是一种设计思想,好比于MVC。就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。
  正控:若调用者需要使用某个对象,其自身就得负责该对象的创建。
  反控:调用者只管负责从Spring容器中获取需要使用的对象,不关心对象的创建过程,也就是把创建对象的控制权反转给了Spring框架。
  控制反转(Ioc),就是依赖注入加上面向接口的编程思想的实现

  示例:

  整体结构:

  深入学习Spring框架(一)- 入门

  CustomService接口:

package com.gjs.service;

public interface CustomeService {
public void say();
}

  实现类CustomServiceImpl1:

package com.gjs.service.impl;

import com.gjs.service.CustomeService;

public class CustomServiceImpl1 implements CustomeService {

    @Override
public void say() {
System.out.println("CustomerServiceImpl1.say()");
}
}

  实现类CustomServiceImpl2:

package com.gjs.service.impl;

import com.gjs.service.CustomeService;

public class CustomServiceImpl2 implements CustomeService {

    @Override
public void say() {
System.out.println("CustomerServiceImpl2.say()");
}
}

  调用方 CustomClient:

package com.gjs.client;

import com.gjs.service.CustomeService;

public class CustomClient {
//1.声明一个接口引用类型
private CustomeService customeService;
//2.spring的依赖注入(DI)需要有一个set方法
public void setCustomeService(CustomeService customeService) {
this.customeService = customeService;
} public void say() {
customeService.say();
}
}

  配置文件 applicationContext.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">
<!--
<bean id="" class = "">
配置让spring管理类的对象的创建
id : 唯一标识
class :被管理类的全限定名
-->
<bean id="client" class="com.gjs.client.CustomClient">
<!-- 依赖注入(DI) :注入被调用方
<property name="" value/ref=""/>
位置:
name : 是set方法确定的属性,不是成员变量
确定属性 : setXxx 方法去掉set前缀 ,剩余部分首字母小写
参数:
value : 值类型注入(字符串,基本数据类型)
ref :引用数据类型(对象), 对应bean的id
-->
<property name="customeService" ref="ServiceImpl1"/>
</bean> <bean id="ServiceImpl1" class="com.gjs.service.impl.CustomServiceImpl1"/>
<bean id="ServiceImpl2" class="com.gjs.service.impl.CustomServiceImpl2"/>
</beans>

  测试类:

package com.gjs.test;

import static org.junit.Assert.*;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.gjs.client.CustomClient;
import com.gjs.service.CustomeService; public class TestSpring {
@Test
public void testName() throws Exception {
//1.读取配置文件,创建Spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取调用方 CustomClient对象
CustomClient client = context.getBean("client", CustomClient.class);
//调用CustomClient对象的say()方法
client.say();
}
}

  应用:

  Spring框架又被称为容器框架,即通过控制反转将各个框架的对象创建交给Spring管理,然后通过依赖注入在层之间传递参数整合框架,并达到低耦合的目的。

  深入学习Spring框架(一)- 入门

9.标签说明

  9.1 bean标签

  作用:用于声明一个类,在启动Spring框架的时候根据该配置的类创建对象到容器里面

<bean id="someBean" class="com.gjs.pojo.SomeBean" scope="prototype"></bean>

id:设置对象名(唯一标识符)(推荐使用)
name:设置对象名(唯一标识符),与id的区别是可以有多个名称,每个名称用逗号隔开。
class:指定对象对应的类
scope:用于设置的对象的作用范围,可选参数如下:

深入学习Spring框架(一)- 入门

  

在Web开发的三层架构中的使用
  Web层:一般都是多例
  Service层 :单例
  DAO层 :单例

  9.2 alias 别名标签  

  作用:为已配置的bean设置别名

bean id="user" name="test" class="com.gjs.pojo.User"/>
<alias name="user" alias="user1"/> 

name:必要属性, 代表为哪一个bean配置别名, 此属性的值为其他bean标签的id或name属性值
alias: 必要属性,命名的别名

10.实例化Bean的四种方式

  1.构造器实例化(无参数构造器):(最常用)

public class SomeBean {
public SomeBean() {
System.out.println("SomeBean.SomeBean()");
}
}
<bean id="someBean" class="com.gjs.pojo.SomeBean"/>

  2.通过静态方法工厂创建(C)

public class SomeBean {
public SomeBean() {
System.out.println("SomeBean.SomeBean()");
}
}
public class SomeBeanFacotry {
//静态工厂方法
public static SomeBean getSomeBean() {
System.out.println("执行静态工厂方法");
return new SomeBean();
}
}
<bean id="someBean" class="com.gjs.pojo.SomeBeanFacotry" factory-method="getSomeBean"/>

  3.通过实体工厂创建(C)

public class SomeBean {
public SomeBean() {
System.out.println("SomeBean.SomeBean()");
}
}
public class SomeBeanFacotry {
//实例工厂方法
public SomeBean getSomeBean() {
System.out.println("执行实例工厂方法");
return new SomeBean();
}
}
<bean id="someBeanfactory" class="com.gjs.pojo.SomeBeanFactory"/>

<bean id="someBean" factory-bean="someBeanfactory" factory-method="getSomeBean"/>

  4.实现FactoryBean接口实例化:实例工厂变种
  实现FactoryBean接口,MyBatis和Spring集成就是使用的这种方式。此种方式,如果没有使用Bean对应的对象,Spring就不会自动创建,只有在使用的时候Spring才会创建对应的对象

public class SomeBean {
public SomeBean() {
System.out.println("SomeBean4.SomeBean4()");
}
}
public class SomeBeanObjectFactory implements FactoryBean<SomeBean>{
//返回的泛型类型对应的对象
@Override
public SomeBean getObject() throws Exception {
SomeBean bean = new SomeBean();
return bean;
}
}
<bean id="someBean" class="cn.zj.domian.SomeBeanObjectFactory"/>

11.初始化和销毁方法

<bean id="someBean" class="......"
<init-method="该类中初始化方法名"/>
  <destroy-method="该类中销毁方法名"/>
</bean>

  init-method:bean生命周期初始化方法,对象创建后就进行调用
  destroy-method:容器被销毁的时候,如果bean被容器管理,会调用该方法。

12.依赖注入的四种方法

  1.setter注入,(属性注入)(常用)

使用setter注入:

1,使用bean元素的<property>子元素设置;

1.简单类型值,直接使用value赋值;
2.引用类型,使用ref赋值;
3.集合类型,直接使用对应的集合类型元素即可。

2,spring通过属性的set方法注入值;
3,在配置文件中配置的值都是string,spring可以自动的完成类型的转换

示例:

员工类

public class Employee {
private Integer age;
private String name;
private Department dept;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Employee [age=" + age + ", name=" + name + ", dept=" + dept + "]";
}
}

  部门类

public class Department {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

  配置文件

<?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="employee" class="com.gjs.pojo.Employee" >
<!-- setter方法注入: 属性注入
<property name="" value="">
name : 属性名称
value : 基本数据类型+String类型的值注入
ref : 引用类型(对象类型)的注入
value 和ref 只能二选一
-->
<property name="age" value="18"></property>
<property name="name" value="张三"></property>
<property name="dept" ref="dept"></property>
</bean>
<!-- 部门 -->
<bean id="dept" class="com.gjs.pojo.Department" >
<property name="id" value="1"/>
<property name="name" value="开发部"/>
</bean>
</beans>

2.构造器注入

使用bean元素的<constructor-arg>子元素设置:

1.默认情况下,constructor-arg的顺序就是构造器参数的顺序
2. constructor-arg的属性

name : 构造方法参数的名称
index :参数的位置从 0 开始
value :值类型注入
ref :引用类型注入
type : 参数的数据类型

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"> <!-- 配置部门 -->
<bean id="department" class="com.gjs.pojo.Department"> <constructor-arg name="id" value="2"/>
<constructor-arg name="name" value="研发部"/>
</bean> <!-- 配置员工 -->
<bean id="emp" class="com.gjs.pojo.Employee">
<!-- 依赖注入 :构造器注入 -->
<constructor-arg name="id" value="1"/>
<constructor-arg name="name" value="张三"/>
<constructor-arg name="dept" ref="department"/>
</bean>
</beans>

  3.p命名空间注入

  使用p命名空间注入先在约束上面引入 p标签
  xmlns:p="http://www.springframework.org/schema/p"

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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="department" class="com.gjs.pojo.Department"
p:id="3"
p:name="销售部"/> <!-- 配置员工 -->
<bean id="emp" class="com.gjs.pojo.Employee"
p:id="1"
p:name="张三"
p:dept-ref="department"/>
</beans>

4.集合类型值注入
用于处理:
  1.键值对 Map 、Properties
  2.数组
  3.集合Set、List

public class CollectionBean {
private Set<String> set;
private List<String> list;
private String[] array;
private Map<String, String> map;
private Properties prop; //读取本地 xxx.properties文件(本质就是一个Map集合)
}
<?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="collectionBean" class="cn.zj.spring.pojo.CollectionBean"> <!-- setter(属性)方法注入 -->
<!-- 1.数组 -->
<property name="arr">
<array>
<value>AAA</value>
<value>BBB</value>
</array>
</property> <!-- 2.set集合 -->
<property name="set" >
<set>
<value>AAA</value>
<value>AAA</value>
<value>BBB</value>
</set>
</property> <!-- 3.list集合 -->
<property name="lsit">
<list>
<value>list1</value>
<value>list1</value>
<value>list2</value>
</list>
</property>
<!-- 4. map集合 -->
<property name="map">
<map>
<entry key="key1" value="value1"/>
<entry key="key2" value="value2"/>
</map>
</property>
<!-- 5.properties 集合 -->
<property name="prop">
<props>
<prop key="propKey1">propValue1</prop>
<prop key="propKey2">propValue2</prop>
</props>
</property>
</bean>
</beans>

13.获得properties文件的值

  1.导入命名空间方法
  将命名空间和约束重新拷贝一份,将对于的全部替换成 context,然后关联context本地schema约束

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
"> </beans>

  2.导入Mysql驱动包和druid连接池jar包

  深入学习Spring框架(一)- 入门

  3.applicationContext.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
"> <!-- 使用context 读取配置文件到spring容器中
<context:property-placeholder location=""/>
location : db.properties文件的位置,必须加上 classpath: 作为前缀
-->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 创建阿里巴巴druid连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close"
>
<!-- 属性注入 setter方法注入-->
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- 最大连接数 -->
<property name="maxActive" value="${jdbc.maxActive}"/>
</bean> </beans>

  测试代码

@Test
public void testSave() throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); DataSource dataSource = context.getBean(DataSource.class, "dataSource");
Connection conn = dataSource.getConnection();
System.out.println("数据库连接对象:"+conn);
}