Spring框架入门简述

mac2026-03-19  3

Spring框架1 - 入门简述

框架

首先我们要理解框架是什么?框架跟类库有什么区别?

框架,框架其实是一个半成品,它对基础的代码进行了封装并提供相应的API,开发者在使用框架是直接调用封装好的api可以省去很多代码编写,从而提高工作效率和开发速度。 其组成部分: jar包、配置文件(全局+单元)、启动代码等。

类库,类库(Class Library),字面意思就是类的集合,是一个综合性的面向对象的可重用类型集合,这些类型包括:接口、抽象类和具体类。

如何学习框架? 对于框架的学习,我们应该要理解框架的理念以及要解决的问题、学习它的配置和调用方式(其实可以理解为如何套用)、按照套路编码。

什么是Spring?

Spring 是最受欢迎的企业级 Java 应用程序开发框架,是为了解决企业应用程序开发复杂性而创建的。

Spring 框架是一个开源的 Java 平台,它最初是由 Rod Johnson 编写的,并且于 2003 年 6 月首次在 Apache 2.0 许可下发布。

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。Spring使用基本的JavaBean来完成以前只可能由EJB(Enterprise Java Bean)完成的事情。

Spring 框架的核心特性是可以用于开发任何 Java 应用程序,但是在 Java EE 平台上构建 web 应用程序是需要扩展的。 Spring 框架的目标是使 J2EE 开发变得更容易使用,通过启用基于 POJO 编程模型来促进良好的编程实践。

Spring框架的好处

1.放便解耦,简单开发 通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。

2.Aop 编程支持 通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。

3.声明事务的支持 在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。

4.方便程序的测试 可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。

5.方便框架的集合 Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供 了对各种优秀框架(如Struts、Hibernate、Hessian、 Quartz) 等的直接支持。

6.降低开发难度 Spring对很多难用的Java EE API (如JDBC, JavaMail, 远程调用等)提供了一-个薄薄的封装层, 通过Spring的简易封装,这些Java EE API的使用难度大为降低。

Spring核心概念简述

控制反转(IoC):即Inversion of Control。举例来说,在以前的项目中,要想调用一个类中的普通方法,则必须创建这个类的实例,再通过这个实例来调用其方法。而在Spring中,你不必再使用这种形式来创建对象,具体过程都交由Spring进行配置来实现。

面向切面编程(AOP):aop是一种编程技术,它允许程序员对横切关注点或横切典型的职责分界线的行为(例如日志和事务管理)进行模块化。AOP 的核心构造是切面,它将那些影响多个类的行为封装到可重用的模块中。

Spirng模块

组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:

核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。

Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。

Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。

Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。

Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。

Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

spring-beans : ioc 实现,配置文件的访问、创建和管理

SpEL : spring的表达式支持

Aspects: 对AspectJ框架的支持

instrumentation: 字节码操作

messaging : 对消息服务的支持

transactions : 事务支持

JDBC : spring对JDBC的封装

ORM : spring对于ORM框架的支持

web : 对于web开发的支持

Spring项目示例

核心理念: IoC inversion of control 控制反转 / DI dependency injection 依赖注入

控制权从调用的类转换到spring容器,由spring来实例化对象及依赖注入

1) 创建对象 2)依赖注入 ( 为属性填入实例)

Spring项目搭建(基于Idea)

建一个简单的登录项目吧。

之前已经配置好了maven,在此就不多说。

导包

在pom.xml加入依赖。自动导入jar包

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.0.RELEASE</version> </dependency>

搭建结构

DAO

public interface UserDAO { String login(String username, String password); }

DAO实现

public class UserDAOImpl implements UserDAO { @Override public String login(String username, String password) { //暂时不与数据库交互,直接返回字符串测试是否执行 return "UserDAOImpl执行了。。。"; } }

Service

public interface UserService { String login(String username, String password); }

Service实现

public class UserServiceImpl implements UserService { //此时我们声明UserDAO,但并不创建对象 private UserDAO userDAO; @Override public String login(String username, String password) { //直接通过声明调用方法 return userDAO.login(username,password); } //创建setter方法 public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } }

Controller

public class UserController { //声明userService private UserService userService; public String login(String username,String password){ //通过声明直接调用方法 return userService.login(username,password); } //创建setter方法 public void setUserService(UserService userService) { this.userService = userService; } }

创建xml文件并配置

创建applicationContext.xml。通过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"> <!--通过setter注入--> <bean id="userController" class="com.alter.spring.controller.UserController"> <!--通过ref引入已存在的bean--> <property name="userService" ref="userService"/> </bean> <bean id="userService" class="com.alter.spring.service.impl.UserServiceImpl"> <property name="userDAO" ref="userDAO"/> </bean> <bean id="userDAO" class="com.alter.spring.dao.impl.UserDAOImpl"/> </beans>

编写测试类

public class App { public static void main(String[] args) { //创建一个spring容器 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); //从容器中获取一个叫做userController的bean并转换为userController的实例 UserController userController = ac.getBean("userController", UserController.class); //调用 String result = userController.login("abc", "123"); System.out.println(result); } }

运行之后打印如下: 从这个例子可以看出,spring框架通过xml配置来获得实例,我们可以将Ioc理解成一个容器,通过xml配置来获得bean实例,并将这些实例保存在容器中。 但是得到实例之后里面的属性又如何注入呢?bean实例化配置只有这种方法吗? 下面我们就讲一讲xml其他的配置方式。

xml具体配置方式

1. xml属性配置(下面以UserController为例)

通过value 注入基本类型 首先我们在controller加入一个基本类型的属性age

public class UserController { //基本属性age private String age; //setter方法 public void setAge(String age) { this.age = age; } ... }

xml配置:

<bean id="userDAO" class="com.alter.spring.dao.impl.UserDAOImpl"> <!-- 通过value配置基本属性--> <property name="age" value="18" /> </bean>

ref 注入已有的bean java类:

public class UserController { //声明userservice private UserService userService; //setter方法 public void setUserService(UserService userService) { this.userService = userService; } ... }

xml配置:

<bean id="userController" class="com.alter.spring.controller.UserController"> <!-- 通过ref配置容器中已存在的bean--> <property name="userService" ref="userService"/> </bean>

List \ Set \ Map等复杂类型配置 java配置

public class UserController { //声明list集合 private List<String> list; //创建setter方法 public void setList(List<String> list) { this.list = list; } //声明map集合 private Map<String, String> map; //创建setter方法 public void setMap(Map<String, String> map) { this.map = map; } //声明set集合 private Set<Integer> set; //创建setter方法 public void setSet(Set<Integer> set) { this.set = set; } ... }

xml配置

<bean id="userDAO" class="com.alter.spring.controller.UserController"> <!-- 通过name指定List属性名,value配置具体的属性值--> <property name="list"> <list> <value>manager</value> <value>farmer</value> <value>driver</value> </list> </property> <!-- 通过name指定Map属性名,<entry>配置具体的属性值--> <property name="map"> <map> <entry key="pig" value="pink"/> <entry key="cat" value="orange"/> </map> </property> <!-- 通过name指定Set属性名,value配置具体的属性值--> <property name="set" > <set> <value>2</value> </set> </property> </bean>

最后我们验证这些属性是否配置成功,在login方法中加入输出语句。

public class UserController{ ... public String login(String username,String password){ System.out.println("age="+age); System.out.println("list="+list); System.out.println("map="+map); System.out.println("set="+set); return userService.login(username,password); } }

这时IDEA打印如下,说明属性配置成功。

2. bean的实例化

默认构造器实例化 上述的实例中,在xml文件中配置bean实例其实是调用指定类的默认的无参构造方法。(可以给定其有参构造,此时就会抛出异常,在此省略验证步骤)

静态工厂方法实例化

<!--用静态工厂方法创建一个connection作为springbean--> <bean id="connection" factory-method="getConnection" class="com.alter.spring.common.JDBCUtils"/> <!--某个类(JDBCUtils)的静态方法(getConnection),返回值作为bean-->

工厂bean实例化

<!--工厂bean--> <bean id="holidayFactory" class="com.alter.spring.factory.HolidayFactory"/> <!--holidayBean--> <bean id="holiday" factory-bean="holidayFactory" factory-method="create"></bean> public class HolidayFactory { public Holiday create(){ return new Holiday(); } }

Spring的FactoryBean接口实例化

一个类实现FactoryBean接口,实现其方法

配置之后,bean的实例为FactoryBean的getObject方法的返回值

public class CarFactory implements FactoryBean<Car> { @Override public Car getObject() throws Exception { return new Car(); } @Override public Class<?> getObjectType() { return Car.class; } } <bean id="car" class="com.alter.spring.factory.CarFactory"/>
3. 核心API
BeanFactory IOC容器的基本接口ApplicationContext 可用的IOC容器接口ClassPathXmlApplicationContext xml配置文件的IOC容器
4. 依赖注入
setter注入 如上面的例子就是采用setter方法注入属性。构造器注入

<constructor-arg name index>

index : 用于指定要注入的数据给构造函数中指定索引位置的参数赋值,索引的位置时从0开始name(常用) : 用于指定给构造函数中指定名称的参数赋值

设置 value ref list set

<bean id="userService" scope="singleton" class="com.alter.spring.injection.UserServiceImpl" > //可以使用name <constructor-arg name="userDAO" ref="userDAO"></constructor-arg> <constructor-arg name="serviceId" value="12306"/> <constructor-arg name="data" > //或者使用index <constructor-arg index="0" ref="userDAO"></constructor-arg> <constructor-arg index="1" value="12306"/> <constructor-arg index="2" > <list> <value>xiong</value> <value>nian</value> <value>haha</value> </list> </constructor-arg> </bean> public class UserServiceImpl implements UserService { private UserDAO userDAO; private int serviceId; private List<String> data; public UserServiceImpl(UserDAO userDAO,int serviceId,List<String> data){ this.userDAO = userDAO; this.serviceId=serviceId; this.data =data; }; }

特点:在获取 bean 对象时,注入数据是必须的操作,否则无法操作成功

弊端:改变了 bean 对象的实例化方式,使我们在用不到这些数据的情况下也必须提供带参构造函数,因此开发中较少使用此方法,除非避无可避

5. bean的作用域 默认单例
prototype 原型 => 每次创建一个实例[*]singleton 单例 => 一个bean的定义,只有一个实例,不是一个类只有一个实例request 一个请求一个实例session 一个会话一个实例websocket 一次websocket链接一个实例
6. bean的生命周期

在bean配置上写init-method和destroy-method

<bean id="cycle" class="com.alter.spring.lifeCycle.Cycle" init-method="beginning" destroy-method="ending"/> public class Cycle { public void beginning(){ System.out.println("开始"); } public void ending(){ System.out.println("结束"); } }

实现InitializingBean和DisposableBean及其方法

<bean id="cycle2" class="com.alter.spring.lifeCycle.Cycle2"/> //因为实现了接口,spring可以识别,所以不需要写intit和destroy public class Cycle2 implements InitializingBean, DisposableBean { @Override public void afterPropertiesSet() throws Exception { System.out.println("开始...."); } @Override public void destroy() throws Exception { System.out.println("结束了...."); } }
最新回复(0)