1. 什么是spring,它能够做什么?
Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。
Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。
然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
目的:解决企业应用开发的复杂性
功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
范围:任何Java应用
简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
2. 什么是控制反转(或依赖注入)
控制反转(IoC=Inversion of Control)IoC,用白话来讲,就是由容器控制程序之间的(依赖)关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:(依赖)控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。
IoC还有一个另外的名字:“依赖注入 (DI=Dependency Injection)” ,即由容器动态的将某种依赖关系注入到组件之中
使用spring框架 先导入依赖
pom.xml:
<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.lww</groupId> <artifactId>T224_spring</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>T224_spring 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> <!-- 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>T224_spring</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>
写一个接口 定义一个方法
UserBiz:
package com.liuwenwu.ioc.biz; /** * 需求: * 上传文件需求 * 完成的思路:完成功能就好 文件上传就行 * 客户使用的时候:嫌弃上传的事件过长,要求优化 * 由于某程序员的失误,改动的代码影响了其他模块的正常使用 * * 客户:两头利害取其轻,情愿回退上一个版本 * * @author ASUS * */ public interface UserBiz { public void read(); }
两个实现类来实现接口:
UserBizImpl1:
package com.liuwenwu.ioc.biz.impl; import com.liuwenwu.ioc.biz.UserBiz; public class UserBizImpl1 implements UserBiz{ @Override public void read() { System.out.println("死记硬背"); } }
UserBizImpl2:
package com.liuwenwu.ioc.biz.impl; import com.liuwenwu.ioc.biz.UserBiz; public class UserBizImpl2 implements UserBiz{ @Override public void read() { System.out.println("边学习边记笔记,最后举一反三"); } }
spring管理Bean的方式(注入方式)
set注入
基本数据类型
引用数据类型
UserAction定义属性,提供set方法
package com.liuwenwu.ioc.web; import java.util.ArrayList; import java.util.List; import com.liuwenwu.ioc.biz.UserBiz; import com.liuwenwu.ioc.biz.impl.UserBizImpl1; /** * 弊端: * 当需求变化非常快的时候,不便于维护,因为维护的权利是属于程序员的 * * spring的ioc就是解决这一问题的 * 将维护代码的权利由程序员转交给spring容器来完成 * * 1、spring管理Bean的方式(注入方式) * set注入 * 基本数据类型 * 引用数据类型 * 构造注入 * 自动装配 * * @author ASUS * */ public class UserAction { // 实际开发中可能不止一个action实现这个接口 // private UserBiz userBiz =new UserBizImpl1(); private UserBiz userBiz; private int uid; private String uname; private List<String> hobby=new ArrayList<String>(); //提供set方法 // public void setUid(int uid) { // this.uid = uid; // } // // public void setUname(String uname) { // this.uname = uname; // } public void setHobby(List<String> hobby) { this.hobby = hobby; } public void setUserBiz(UserBiz userBiz) { this.userBiz = userBiz; } // 提供构造方法 public UserAction(int uid, String uname) { super(); this.uid = uid; this.uname = uname; } public UserAction() { super(); } /** * set注入 */ public void test1() { System.out.println("uid:"+this.uid); System.out.println("uname:"+this.uname); System.out.println("hobby:"+this.hobby); } /** * 构造注入 */ public void test2() { } /** * 测试注入引用类型 */ public void test3() { userBiz.read(); } }
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"> <!-- id是唯一的 --> <bean id="userBiz" class="com.liuwenwu.ioc.biz.impl.UserBizImpl2"></bean> <!-- 管理多个 实现同一个接口--> <!-- <bean id="userBiz2" class="com.liuwenwu.ioc.biz.impl.UserBizImpl1"></bean> --> <bean id="userAction" class="com.liuwenwu.ioc.web.UserAction"> <!-- set注入 --> <!-- <property name="uid" value="22"></property> --> <!-- <property name="uname" value="zs"></property> --> <property name="userBiz" ref="userBiz"></property> <!-- 构造方法注入 --> <constructor-arg name="uid" value="22"></constructor-arg> <constructor-arg name="uname" value="zs"></constructor-arg> <property name="hobby"> <list> <value>篮球</value> <value>RAP</value> <value>玩蛇</value> </list> </property> </bean> </beans>
模拟浏览器发请求请求后台 Demo1:
package com.liuwenwu.ioc.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.liuwenwu.ioc.web.UserAction; /** * 模拟浏览器发请求请求后台 * @author ASUS * */ public class Demo1 { public static void main(String[] args) { // UserAction userAction =new UserAction(); // userAction.test1(); // 从spring获取 ApplicationContext context=new ClassPathXmlApplicationContext("/spring-context.xml"); UserAction bean = (UserAction) context.getBean("userAction"); // bean.test1(); bean.test3(); } }
构造方法注入 提供构造方法
// 提供构造方法 public UserAction(int uid, String uname) { super(); this.uid = uid; this.uname = uname; } public UserAction() { super(); }
spring-context.xml中配置
<!-- 构造方法注入 --> <constructor-arg name="uid" value="22"></constructor-arg> <constructor-arg name="uname" value="zs"></constructor-arg>
set注入引用数据类型
private UserBiz userBiz;
<!-- 引用一个bean文件 把实体类注入接口--> <bean id="userBiz" class="com.liuwenwu.ioc.biz.impl.UserBizImpl2"></bean> <!-- 引用类型注入 --> <property name="userBiz" ref="userBiz"></property>
spring自动装配:
default-autowire="byType" 根据类型装配 如果多个类实现一个接口 就会报错
default-autowire="byName" 根据名字装配 用的多
将spring的上下文交给Tomcat上下文进行管理
SpringLoadListener:
package com.liuwenwu.ioc.test; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * 2、如何将spring的上下文交给Tomcat上下文进行管理 * 首先spring上下文为什么交给tomca? * 分析:目前工程中所用javabean都交给了spring进行管理,那么浏览器发送请求 * 请求的是Tomcat,由Tomcat来处理请求,Tomcat处理请求一般来说都要访问数据库 * 数据库是由dao层访问的,dao层的实体类又是交给了spring是上下文管理,那就意味着 * Tomcat要处理请求,必须拿到spring的上下文,才能够拿到dao层的javabean * @author ASUS * */ //监听器 @WebListener public class SpringLoadListener implements ServletContextListener { // 配置文件地址 private String springXmlLocation=""; //重写 @Override // Tomcat启动就会加载 public void contextInitialized(ServletContextEvent sce) { System.out.println("监听了Tomcat的启动..."); // 获取Tomcat上下文 ServletContext servletContext = sce.getServletContext(); springXmlLocation=servletContext.getInitParameter("springXmlLocation"); if(springXmlLocation==null ||"".equals(springXmlLocation)) { springXmlLocation="spring-context.xml"; } System.out.println("springXmlLocation"+springXmlLocation); // spring上下文 ApplicationContext springContext=new ClassPathXmlApplicationContext(springXmlLocation); // 将spring上下文交给Tomcat上下文 servletContext.setAttribute("SPRING_CONTEXT_KEY", springContext); } }
UserServlet:
package com.liuwenwu.ioc.test; import java.io.IOException; import javax.servlet.ServletContext; 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.liuwenwu.ioc.web.UserAction; @WebServlet("/user") public class UserServlet extends HttpServlet { private static final long serialVersionUID = 3011793850996016507L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 拿到上下文 ServletContext servletContext = req.getServletContext(); ApplicationContext springContext=(ApplicationContext) servletContext.getAttribute("SPRING_CONTEXT_KEY"); UserAction bean=(UserAction) springContext.getBean("userAction"); bean.test3(); } }
调用成功说明spring上下文交给了Tomcat上下文进行管理
意味着每一个servlet都能获取到spring上下文管理的所有的bean文件
<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> <context-param> <param-name>springXmlLocation</param-name> <param-value>/spring-other.xml</param-value> </context-param> </web-app>
可以变更配置文件