目录
一、Spring启示录
1.1OCP开闭原则
1.2DIP依赖倒置原则
1.3IoC控制反转
1.4DI依赖注入
二、Spring概述
2.1Spring简介
2.2Spring八大模块
2.3Spring特点
三、Spring的入门程序
3.1Spring的文件
3.2第一个Spring程序
3.3第一个Spring程序详细剖析
3.4Spring6启用Log4j2日志框架
阅读以下代码:
userDao
package com.powernode.spring6.web;
import com.powernode.spring6.service.UserService;
import com.powernode.spring6.service.impl.UserServiceImpl;
public class UserAction {
//private UserService userService = new UserServiceImpl();
// 修改为
private UserService userService;
/**
* 删除用户信息的请求
*/
public void deleteRequest(){
userService.deleteUser();
}
}
UserDaoImplForMySQL
package com.powernode.spring6.dao.impl;
import com.powernode.spring6.dao.UserDao;
public class UserDaoImplForMySQL implements UserDao {
@Override
public void deleteById() {
System.out.println("MySQL数据库正在删除用户信息......");
}
}
UserDaoImplForOracle
package com.powernode.spring6.dao.impl;
import com.powernode.spring6.dao.UserDao;
public class UserDaoImplForOracle implements UserDao {
@Override
public void deleteById() {
System.out.println("Oracle数据库正在删除用户数据....");
}
}
UserService
package com.powernode.spring6.service;
public interface UserService {
/**
* 删除用户信息
*/
void deleteUser();
}
UserServiceImpl
package com.powernode.spring6.service.impl;
import com.powernode.spring6.dao.UserDao;
import com.powernode.spring6.dao.impl.UserDaoImplForMySQL;
import com.powernode.spring6.dao.impl.UserDaoImplForOracle;
import com.powernode.spring6.service.UserService;
public class UserServiceImpl implements UserService {
//private UserDao userDao = new UserDaoImplForMySQL();
// 修改为
//private UserDao userDao = new UserDaoImplForOracle();
private UserDao userDao;
@Override
public void deleteUser() {
userDao.deleteById();
}
}
UserAction
package com.powernode.spring6.web;
import com.powernode.spring6.service.UserService;
import com.powernode.spring6.service.impl.UserServiceImpl;
public class UserAction {
//private UserService userService = new UserServiceImpl();
// 修改为
private UserService userService;
/**
* 删除用户信息的请求
*/
public void deleteRequest(){
userService.deleteUser();
}
}
Test
package com.powernode.spring6.client;
import com.powernode.spring6.web.UserAction;
public class Test {
public static void main(String[] args) {
UserAction userAction = new UserAction();
userAction.deleteRequest();
}
}
以上代码违背了OCP开闭原则。
什么是OCP开闭原则?
OCP是软件七大开发原则当中最基本的一个原则:开闭原则。
对扩展开放。
对修改关闭。
OCP原则是最核心的、最基本的,其它六个原则都是为这个原则服务的。
OCP开闭原则的核心:只要在扩展系统功能的时候没有修改之前写好的代码,那么就是符合OCP原则的。反之,违背了OCP原则。
当系统功能扩展的时候,如果修改了之前稳定的程序,之前所有的程序都需要进行重新测试,非常麻烦。
什么是依赖倒置原则?
面向接口编程,面向抽象编程,不要面向具体编程。
依赖倒置原则的目的?
降低程序之间的耦合度,提高扩展力。
什么是符合依赖倒置?
上不依赖下。
什么是违背倒置原则?
上依赖下。只要“下”一改动,“上”就收到牵连。
当前的程序显然违背OCP、DIP原则,怎么办?
可以采用“控制反转”这种编程思想来解决这个问题。
什么是控制反转?
Spring框架实现了控制反转IoC这种思想。
Spring框架可以帮你new对象。
Spring框架可以帮你维护对象与对象之间的关系。
Spring是一个实现了IoC思想的容器。
控制反转的实现方式有多种,其中比较重要的是:依赖注入(Dependency Injection,简称DI)。
控制反转是思想,依赖注入是这种思想的具体实现。
依赖注入DI,又包括常见的两种方式:
set注入(执行set方法给属性赋值)
构造方法注入(执行构造方法给属性赋值)
依赖注入中”依赖“是什么意思?”注入“是什么意思?
依赖:A对象和B对象的关系。
注入:是一种手段,通过这种手段,可以让A对象和B对象产生关系。
依赖注入:对象A和对象B之间的关系,通过注入的手段来维护。而注入包括:set注入和构造注入。
Spring是一个开源框架,它是为了解决企业应用开发的复杂性而创建的。
从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
Spring最初的出现是为了解决EJB臃肿的设计,以及难以测试等问题。
Spring为简化开发而生,让程序员只需关注核心业务的实现,尽可能的不在关注非业务逻辑代码(事务控制,安全日志等)。
注意:Spring5版本之后是8个模块。在Spring5中新增了WebFlux模块。
轻量
从大小与开销两方面而言,Spring都是轻量级的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布,并且Spring所需的处理开销也是微不足道的。
Spring是非侵入式的:Spring应用中的对象不依赖于Spring的特定类。
控制反转
Spring通过⼀种称作控制反转(IoC)的技术促进了松耦合。当应⽤了IoC,⼀个对象依赖的其它对象会通过被动的⽅式传递进来,⽽不是这个对象⾃⼰创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,⽽是容器在对象初始化时不等对象请求就主动将依赖传递给它。
面向切面
Spring提供了⾯向切⾯编程的丰富⽀持,允许通过分离应⽤的业务逻辑与系统级服务(例如审
计(auditing)和事务(transaction)管理)进⾏内聚性的开发。应⽤对象只实现它们应该做
的——完成业务逻辑——仅此⽽已。它们并不负责(甚⾄是意识)其它的系统级关注点,例如
⽇志或事务⽀持。
容器
Spring包含并管理应⽤对象的配置和⽣命周期,在这个意义上它是⼀种容器,你可以配置你的
每个bean如何被创建——基于⼀个可配置原型(prototype),你的bean可以创建⼀个单独的实例或者每次需要时都⽣成⼀个新的实例——以及它们是如何相互关联的。然⽽,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞⼤与笨重的,难以使⽤。
框架
Spring可以将简单的组件配置、组合成为复杂的应⽤。在Spring中,应⽤对象被声明式地组
合,典型地是在⼀个XML⽂件⾥。Spring也提供了很多基础功能(事务管理、持久化框架集成
等等),将应⽤逻辑的开发留给了你。
Spring的jar文件
JAR文件 | 描述 |
---|---|
spring-aop-5.3.9.jar | 这个jar 文件包含在应用中使用Spring 的AOP 特性时所需的类 |
spring-aspects-5.3.9.jar | 提供对AspectJ的支持,以便可以方便的将面向切面的功能集成进IDE中 |
spring-beans-5.3.9.jar | 这个jar 文件是所有应用都要用到的,它包含访问配置文件、创建和管理bean 以及进行Inversion ofControl / Dependency Injection(IoC/DI)操作相关的所有类。如果应用只需基本的IoC/DI 支持,引入spring-core.jar 及spring-beans.jar 文件就可以了。 |
spring-context-5.3.9.jar | 这个jar 文件为Spring 核心提供了大量扩展。可以找到使用Spring ApplicationContext特性时所需的全部类,JDNI 所需的全部类,instrumentation组件以及校验Validation 方面的相关类。 |
spring-context-indexer-5.3.9.jar | 虽然类路径扫描非常快,但是Spring内部存在大量的类,添加此依赖,可以通过在编译时创建候选对象的静态列表来提高大型应用程序的启动性能。 |
spring-context-support-5.3.9.jar | 用来提供Spring上下文的一些扩展模块,例如实现邮件服务、视图解析、缓存、定时任务调度等 |
spring-core-5.3.9.jar | Spring 框架基本的核心工具类。Spring 其它组件要都要使用到这个包里的类,是其它组件的基本核心,当然你也可以在自己的应用系统中使用这些工具类。 |
spring-expression-5.3.9.jar | Spring表达式语言。 |
spring-instrument-5.3.9.jar | Spring3.0对服务器的代理接口。 |
spring-jcl-5.3.9.jar | Spring的日志模块。JCL,全称为"Jakarta Commons Logging",也可称为"Apache Commons Logging"。 |
spring-jdbc-5.3.9.jar | Spring对JDBC的支持。 |
spring-jms-5.3.9.jar | 这个jar包提供了对JMS 1.0.2/1.1的支持类。JMS是Java消息服务。属于JavaEE规范之一。 |
spring-messaging-5.3.9.jar | 为集成messaging api和消息协议提供支持 |
spring-orm-5.3.9.jar | Spring集成ORM框架的支持,比如集成hibernate,mybatis等。 |
spring-oxm-5.3.9.jar | 为主流O/X Mapping组件提供了统一层抽象和封装,OXM是Object Xml Mapping。对象和XML之间的相互转换。 |
spring-r2dbc-5.3.9.jar | Reactive Relational Database Connectivity (关系型数据库的响应式连接) 的缩写。这个jar文件是Spring对r2dbc的支持。 |
spring-test-5.3.9.jar | 对Junit等测试框架的简单封装。 |
spring-tx-5.3.9.jar | 为JDBC、Hibernate、JDO、JPA、Beans等提供的一致的声明式和编程式事务管理支持。 |
spring-web-5.3.9.jar | Spring集成MVC框架的支持,比如集成Struts等。 |
spring-webflux-5.3.9.jar | WebFlux是 Spring5 添加的新模块,用于 web 的开发,功能和 SpringMVC 类似的,Webflux 使用当前一种比较流程响应式编程出现的框架。 |
spring-webmvc-5.3.9.jar | SpringMVC框架的类库 |
spring-websocket-5.3.9.jar | Spring集成WebSocket框架时使用 |
注意:如果你只是想要用Spring的IoC功能,仅需引入:spring-context即可。如果采用maven只需要引入context的依赖即可。
org.springframework
spring-context
6.0.3
第一步:添加spring context、junit依赖,pom.xml配置如下
4.0.0
com.hhb
spring002-first
1.0-SNAPSHOT
jar
org.springframework
spring-context
6.0.3
junit
junit
4.13.2
test
20
20
UTF-8
注意:打包方式jar。
当加入spring context依赖后,会关联引入其他依赖:
spring aop:面向切面编程
spring beans:IoC核心
spring core:spring的核心工具包
spring jcl:spring的日志包
spring expression:spring表达式
第二步:定义bean:User
package com.hhb.bean;
public class User {
}
第三步:编写spring的配置文件:spring.xml。该文件放在类的根路径下。
Spring的配置文件,IDEA工具提供了这个模板,一定要使用这个模板来创建。
bean的id和class属性:
id:是中国bean的身份证号,不能重复,是唯一的标识。
class:必须填写类的全路径,全限定类名。(带包名的类名)
第四步:编写测试程序
package com.hhb.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FirstSpringTest {
@Test
public void testFirstSpringCode() {
/*
* 第一步:获取Spring容器对象
* ApplicationContext 翻译为:应用上下文,其实就是Spring容器。
* ApplicationContext 是一个接口。
* ApplicationContext 接口下有很多实现类,其中有一个实现类叫做:ClassPathXmlApplicationContext
* ClassPathXmlApplicationContext 专门从类路径中加载spring配置文件的一个Spring上下文对象
* 这行代码只要执行就相当于启动了Spring容器,解析spring.xml文件,并且实例化所有的bean对象,放到spring容器当中。
* */
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
//第二步:根据bean的id从spring容器中获取这个对象
Object userBean = applicationContext.getBean("userBean");
System.out.println(userBean);
}
}
在spring的配置文件中,bean标签的id是不能重名的。
底层通过反射机制调用类的无参构造方法创建对象的,所以要想让spring创建对象,必须保证无参数构造方法是存在的。
将创建好的对象存储到了Map集合中。
spring配置文件的名字是随意的。
spring的配置文件可以有多个。
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml", "beans.xml", "xml/beans.xml");
在配置文件中配置的类不一定是自定义的,可以使用JDK中的类。
spring.xml
Test
@Test
public void testFirstSpringCode() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml", "beans.xml", "xml/beans.xml");
Object userBean = applicationContext.getBean("userBean");
System.out.println(userBean);
//Object nowTime = applicationContext.getBean("nowTime");
//Date nowTime = (Date) applicationContext.getBean("nowTime");
//不想强制类型转换,可以使用以下代码(通过第二个参数来指定返回的bean类型)
Date nowTime = applicationContext.getBean("nowTime", Date.class);
//如果bean的id不存在,不会返回null,而是出现一次
//日期格式化
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
String strNowTime = simpleDateFormat.format(nowTime);
System.out.println(strNowTime);
}
getBean()方法调用时,当指定的id不存在时,会出现异常。
getBean()方法返回的类型时Object,如果访问子类的特有属性和方法时,还需要向下转型,解决方法:
User user = applicationContext.getBean("userBean", User.class);
ClassPathXmlApplicationContext是从类路径中加载配置文件,如果没有在类路径中,需要使用FileSystemXmlApplicationContext类进行加载配置文件。这种方式很少用,一般都是将配置文件放到类路径中的,这样可移植性更强。
BeanFactory是Spring容器的超级接口,ApplicationContext是BeanFactory的子接口。
从Spring5之后,Spring框架支持集成的日志框架是Log4j2。
如何启用日志框架:
第一步:引入Log4j2的依赖
org.apache.logging.log4j
log4j-core
2.19.0
org.apache.logging.log4j
log4j-slf4j2-impl
2.19.0
第二步:放在类的根路径下提供log4j2.xml配置文件(文件名固定为log4j2.xml,文件必须放到类的根路径下)
第三步:使用日志框架
@Test
public void testBeginInitBean() {
//注意:不是在调用getBean()方法的时候创建对象,执行以下代码的时候,就会实例化对象。
new ClassPathXmlApplicationContext("spring.xml");
//使用log4j2记录日志信息
//第一步:创建日志记录器对象
//获取FirstSpringTest类的日志记录器对象,也就是说只要是FirstSpringTest类中的代码执行记录日志的话,就输出相关的日志信息。
Logger logger = LoggerFactory.getLogger(FirstSpringTest.class);
//第二步:记录日志,根据不同的级别来输出日志
logger.info("消息");
logger.debug("调试");
logger.error("错误");
}