1.Spring框架概述
什么是Spring?
Spring是一个开源的,轻量级Java开发框架;
是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson
在其著作 Expert One-On-One J2EE Development and Design 中阐述的部分理念和原型衍生而来。
其核心特性是可以用于开发任何 Java 应用程序,Spring 框架的目标是使 JavaEE应用程序的开发变得更加容易,核心概念是IOC和AOP;
Spring不是针对某个具体功能,具体层级的框架;
也就是说以前该有的系统分层,结构,设计模式都不需要改变,而是让Spring加入进来,让开发变得更简单;
记住Spring并不想取代某个已存在的框架,从简单性、可测试性和松耦合的角度而言,任何 Java 应用都可以从 Spring 中受益。反而可以让各个框架的配合使用难度降低,它可以快速的在系统中集成其他优秀的框架。
Spring 的用途不仅限于服务器端的开发。简单来说,Spring 是一个分层的 JavaSE/EEfull-stack(一站式) 轻量级开源框架。
为什么需要Spring
Spring VS EJB
我们经常会看到Spring替代EJB,或Spring与EJB对比,那么两者之间到底有什么关系呢?
EJB是JavaEE规范中的一个,主要用于开发分布式应用程序
Spring是一个框架,框架是帮你实现了一部分功能的半成品
EJB是一个规范,用来规范(指导)开发者,如何去实现JavaEE程序
所以这个问题其实是在问Spring(框架)和JavaEE(规范)的对比,而因为两者不是同一种概念,所以无法直接对比,那到底在对比啥?
对比的是:
使用Spring开发和完全按照JavaEE规范开发应用程序的区别
推出Spring是因为民间开发者对官方规范的不足提出的质疑以及做出的强力回应,在早期阶段,开发者们从最早的JavaEE这一官方协议推出后,开发者们非常拥戴,后来慢慢发现这堆复杂,晦涩,学习成本极高的规范是多么的臃肿不堪,就在这时候Spring框架应运而生,因其轻量级,使用简单很快受到了大家的喜爱;
说白了就是官方给的台臃肿、复杂、晦涩不好用。这时候民间就推出了Spring
EJB容器和IOC容器
另一方面因为Spring具备IOC容器,可以帮助我们管理Bean;
而EJB的需要放在EJB容器中才能使用其提供的功能;
EJB主要用于提供分布式能力;
而IOC容器是帮助我们更好的解耦;
Spring的优点
- Spring 对JavaEE中的一些API(JDBC、JavaMail、远程调用等),提供了封装,使这些API使用难度降低;
- 一站式框架,可简单快速的集成其他框架;
- IOC,利用依赖注入,极大的降低各组件间的耦合,提高整体扩展性;
- AOP(面向切面)编程的支持,可以方便的对程序进行权限拦截,运行监控等;
- 声明式事务支持,通过配置就可以完成对事务的管理,无序进行手动编程;
- 容器化,Spring包含并管理应用对象的配置和生命周期,你可以配置每个bean如何被创建以及bean是一个单独的实例或者每次需要时都生成一个新的实例,以及它们是如何相互关联的
IOC和DI
概念
控制反转(Inversion of Control,缩写为IOC),是面向对象编程中的一种设计原则,可以用来降低计算机代码之间的耦合度。将原本由程序实现的一部分逻辑反过来交给系统来完成就称之为控制反转。
其中最常见的方式叫做依赖注入(Dependency Injection,简称DI)通过控制反转,可以说,依赖被注入到对象中。依赖注入是实现控制反转的一种手段;
IOC和DI的区别
IOC :控制反转,将对象的创建权交给了 Spring。
DI :Dependency Injection 依赖注入。需要有 IOC 的环境,Spring 创建这个类的过程中,Spring 将类的依赖的属性设置进去。
以前需要自己new,在Spring中可以将需要的依赖直接放到对象中,controller不需要关心service如何创建以及具体的细节
为何需要IOC
大多数应用程序,都是有很多不同对象彼此合作来完成业务逻辑,这导致在获取一个合作对象时,必须显示的去new一个对象,这将就导致代码高度耦合并且难以维护和调试。像下面这样:
public class UserController {
UserService userService = new UserService();
public void login(){
userService.login("cx","123");
}
}
当需要更换业务逻辑时,不得不修改源码,若Service层实例化需要参数时,Controller层必须得为其提供参数,这反映了Controller和Service的耦合度还是比较高的。
Spring体系结构
- Core:提供了框架基础组成部分,包括IOC和DI;
- Beans:提供了BeanFactory,时工厂模式的实现,提供了普通对象和单例对象的获取;
- context:建立在Core和Bean的基础上,可以将其他库集成到Spring中;
- expression:又为SpEl(Spring-express-Language),提供了表达式语言支持,其对JSP的EL进行了扩展;
- AOP:提供了面向切面编程实现;
- Aspects:模块提供了与AspectJ的集成,是一个功能强大且成熟的AOp框架;
- instrument:用于代理监控JVM运行的JAVA程序,对字节码修改,以实现AOP;
- Messaging:模块为STOMP提供了支持,主要处理来自WebSocket客户端的STOMP信息。
强调
Spring是模块化的,完全可以根据需要来导入所需模块。
Spring入门
传统写法:
UserService 接口:
package cx.service;
public interface UserService {
public void login(String name, String pwd);
}
UserServiceImpl实现类:
package cx.service.impl;
import cx.service.UserService;
public class UserServiceImpl implements UserService {
public void login(String name, String pwd) {
if (name == "cx" && pwd.equals("123")){
System.out.println("登录成功");
}else {
System.out.println("登录失败");
}
}
}
UserController
package cx.controller;
import cx.service.UserService;
import cx.service.impl.UserServiceImpl;
public class UserController {
//实现Controller需要调用service
//第一种方式:直接new
UserService userService = new UserServiceImpl();
public void login(){
userService.login("cx","123");
}
public static void main(String[] args) {
UserController userController = new UserController();
userController.login();
}
}
上述是一个简单的传统写法,controller调用service层,需要在controller中new一个service,但是如果加入了一个新的service实现类,就需要修改代码,此时就违背了OCP原则,即开放封闭原则。
什么是OCP?
全称叫做开放封闭原则,是在开发应用程序时应当遵循的一个原则。
- open:对扩展开放
- close:对修改源代码封闭
其目的时在不修改元代啊的情况下对已有功能进行扩展。
对于上述传统写法,我们可以优化为,创建一个工厂:
UserServiceFactory
package cx.service;
import cx.service.impl.UserServiceImpl;
public class UserServiceFactory {
public UserService getUserService(){
return new UserServiceImpl();
}
}
UserController通过工厂来获取:
package cx.controller;
import cx.service.UserService;
import cx.service.UserServiceFactory;
import cx.service.impl.UserServiceImpl;
public class UserController {
//实现Controller需要调用service
//第一种方式:直接new
// UserService userService = new UserServiceImpl();
//第二种,通过工厂来获取
UserService userService = new UserServiceFactory().getUserService();
public void login(){
userService.login("cx","123");
}
public static void main(String[] args) {
UserController userController = new UserController();
userController.login();
}
}
上述添加工厂的方式,UserController虽然不需要修改,但是当添加类时需要在工厂类里面修改,所以仍然需要改进,来实现开放封闭原则:
在resources下创建一个my.properties
implClass = cx.service.impl.UserServiceImpl
package cx.service;
import cx.service.impl.UserServiceImpl;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
public class UserServiceFactory {
public UserService getUserService() {
//加载配置文件
Properties properties = new Properties();
try {
//读取配置文件
properties.load(new FileInputStream("D:\\ideaProject\\SpringDemo1\\src\\main\\resources\\my.properties"));
//加载类
String implClass = properties.getProperty("implClass");
//创建实例
Class<?> aClass = Class.forName(implClass);
return (UserService) aClass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
将要执行的类写在里面,通过工厂获取类名,再通过反射获取类,这样就只需要修改这个配置文件,不要修改类:
上述是一个经典思想,如果有多个类的话,需要多个工厂,此时你会发现工厂做的事都是一样的,不一样的就是配置文件路径,返回对象类型,这些都可以进行封装,Spring就是做了这些事。
使用Spring
配置Maven添加Spring依赖:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<!-- Maven会自动下载所有Spring核心容器和aop的依赖-->
</dependencies>
创建配置文件
在resources下创建一个applicationContext.xml
在resources下右键new,如图
<?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标签,创建Service对象,交给容器来管理-->
<bean id="userService" class="cx.service.impl.UserServiceImpl" />
</beans>
bean标签中class是包名+类名,id是自己定义,可以根据id来获取类对象
从Spring中获取需要的对象
package cx.controller;
import cx.service.UserService;
import cx.service.UserServiceFactory;
import cx.service.impl.UserServiceImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserController {
//实现Controller需要调用service
//第一种方式:直接new
// UserService userService = new UserServiceImpl();
//第二种,通过工厂来获取
//UserService userService = new UserServiceFactory().getUserService();
public void login(){
//第三种 读取配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationCotext.xml");
//根据配置文件bean标签的id获取对应对象
UserService userService = (UserService) context.getBean("userService");
userService.login("cx","123");
}
public static void main(String[] args) {
UserController userController = new UserController();
userController.login();
}
}
可以发现,Spring是一个对象工厂,但是着只是Spring的基础功能。