目录
一、什么是Spring
Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。
Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于
服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受
益。
目的:解决企业应用开发的复杂性
功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
范围:任何Java应用
简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
官方的解说确实不怎么生动,哈。请看下图
Spring管理的层面非常的多!如下图
二、IOC控制反转(注入依赖)
概念:
控制反转(IoC=Inversion of Control)IoC,用白话来讲,就是由容器控制程序之间的(依赖)关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:(依赖)控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。
IoC还有一个另外的名字:“依赖注入 (DI=Dependency Injection)” ,即由容器动态的将某种依赖关
系注入到组件之中 。
关于程序某个功能的升级,如果不适用IOC概念,就最原始的方法的话,对功能进行升级,那这是
不是要对源码进行更改!!这是存在非常大的风险的,能不能这样,多写一个类,然后引用。
你可能也觉得原始的写法,我多写一个Biz然后修改action中的调用不就好了吗?一个项目够大的
话,上百个action不成问题,那么真的要去100个action中寻找那些要改吗?效率低!通过Spring的
控制反转,修改xml文件中的映射来达到更新action中引用的BIz。
案例:将用户的下载功能由1.0升级为2.0
①pom中导入相关依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zwf</groupId>
<artifactId>Spring_01</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Spring_01 Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>5.0.1.RELEASE</spring.version>
<javax.servlet.version>4.0.0</javax.servlet.version>
<junit.version>4.12</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- 2、导入spring依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 5.1、junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- 5.2、servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>Spring_01</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
②各层的编写
项目结构
UserAction和UserAction2只是为了演示项目中多个action对Biz的调用!!!不必过纠结。
定义用户结果IUserBiz接口,下载功能
package com.zwf.biz;
/**
* Biz层,用户功能接口
* @author zjjt 老张
*
*/
public interface IUserBiz {
/**
* 下载功能
*/
void load();
}
实现用户功能接口,分别有1.0和2.0版本
UserBiz1.java 1.0
package com.zwf.impl;
import com.zwf.biz.IUserBiz;
/**
* 用户功能接口实现
* @author zjjt 老张
*
*/
public class UserBiz1 implements IUserBiz {
@Override
public void load() {
System.out.println("实现版本1.0的下载功能!");
}
}
UserBiz2.java 2.0
package com.zwf.impl;
import com.zwf.biz.IUserBiz;
/**
* 用户功能接口实现
* 注:下载功能升级1.0-->2.0
* @author zjjt 老张
*
*/
public class UserBiz2 implements IUserBiz{
@Override
public void load() {
System.out.println("实现版本2.0的下载功能!");
}
}
③需要使用到下载功能的action中对功能进行调用
UserAction.java
原始写法
package com.zwf.web;
import com.zwf.biz.IUserBiz;
import com.zwf.impl.UserBiz1;
/**
* 用户接口
*/
public class UserAction2 {
private IUserBiz userBiz = new UserBiz1();
public void load() {
userBiz.load();
}
}
IoC写法
package com.zwf.web;
import com.zwf.biz.IUserBiz;
public class UserAction2 {
private IUserBiz userBiz;
public IUserBiz getUserBiz() {
return userBiz;
}
public void setUserBiz(IUserBiz userBiz) {
this.userBiz = userBiz;
}
public void load() {
userBiz.load();
}
}
可以看到获得到的Biz并不是写死由我们的程序帮我们进行创建,而是由我们控制xml文件来实现具
体哪个biz的赋值。实现了控制反转,控制对象的创建由电脑变成了Spring来完成!
③spring-context.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"
xmlns:aop="http://www.springframework.org/schema/aop"
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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<bean name="userBiz" class="com.zwf.impl.UserBiz1"></bean>
<bean name="userAction2" class="com.zwf.web.UserAction2">
<property name="userBiz" ref="userBiz"></property>
</bean>
</beans>
当非常多的action需要获得UserBiz1类然后调用load()方法,如果UserBiz1load()方法升级变成了UserBiz2,这是不需要去每个类中一个个更改,只需要将name="userBiz"的bean标签中的class改为UserBiz2的全路径!!!
UserAction2中的UserBiz属性必须具备set/get方法,ref为对应的UserBiz配置的标签的name名!
通过解析xml文件来完成UserAction2中的UserBiz属性的赋值!!!
没有get/set方法会报相关错误,
仅仅截取了小部分该错误标识
④ 测试
package com.zwf.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.zwf.web.UserAction;
import com.zwf.web.UserAction2;
public class IocTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-context.xml");
UserAction2 userAction2 = (UserAction2) applicationContext.getBean("userAction2");
userAction2.load();
}
}
测试结果
将配置文件中UserBiz的class改为"com.zwf.impl.UserBiz2"
测试结果:
三、与Tomcat整合
①性能优化
考虑到一点,每次获取对象都要进行一次解析建模操作吗,如果文件足够大,那么这是非常占时间
的,服务器压力也大!!
创建一个监听器,来解决这个问题:
package com.zwf.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringLoaderListener implements ServletContextListener {
/**
* 监听器初始化,在启动时执行一次,之后不再执行!
* 考虑到每次Spring建模影响性能,由监听器在程序运行时仅实现一次建模
*/
public void contextInitialized(ServletContextEvent sce) {
System.out.println("spring-context建模...");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
sce.getServletContext().setAttribute("SpringContext", applicationContext);
}
}
在web.xml文件中进行配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>Archetype Created Web Application</display-name>
<listener>
<listener-class>com.zwf.listener.SpringLoaderListener</listener-class>
</listener>
</web-app>
②servlet测试
package com.zwf.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import com.zwf.biz.IUserBiz;
@WebServlet("/user")
public class UserAction extends HttpServlet{
/**
* servlet启动时执行
*/
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ApplicationContext springContext = (ApplicationContext) req.getServletContext().getAttribute("SpringContext");
IUserBiz userBiz = (IUserBiz) springContext.getBean("userBiz");
userBiz.load();
}
}
servlet中获取Biz的权利交给了Spring
四、Spring对象初始化值设置
通过上面的Biz赋值可以看到,这个传参是在配置文件中进行设置。
可以初始化集合,初始化对象等。
Spring将我们在程序中所有需要到new对象的操作给取代了,变成通过Spring-context.xml模型来进
行获取对象!!