Spring 的 Ioc
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的IoC
IOC/DI
将以前由程序员实例化对象/赋值的工作交给了spring处理
Spring管理javabean的方式(注入):
spring配置文件参数:
3. 如何在spring当中定义和配置一个JavaBean(使用无参构造方法+set方法创建一个JavaBean)
3.1 id:在容器中查找Bean的id(唯一、且不能以/开头)
3.2 class:bean的完整类名
3.3 name:在容器中查找Bean的名字(唯一、允许以/开头、允许多个值,多个值之间用逗号或空格隔开)
3.4 scope:(singleton|prototype)默认是singleton
3.4.1 singleton(单例模式):在每个Spring IoC容器中一个bean定义对应一个对象实例
3.4.2 prototype(原型模式/多例模式):一个bean定义对应多个对象实例
3.4 abstract:将一个bean定义成抽象bean(抽象bean是不能实例化的),抽象类一定要定义成抽象bean,非抽象类也可以定义成抽象bean
3.5 parent:指定一个父bean(必须要有继承关系才行)
3.6 init-method:指定bean的初始化方法
3.7 constructor-arg:使用有参数构造方法创建javaBean
set注入:
基本数据类型
引用数据类型
构造注入:通过构造函数来给配置文件注入,给实体类中加构造方法,把set方法注释掉 然后重新配置constructory-ary,就可以注入成功了
自动装配:
default-autowire="byType"是根据类别来进行查找
default-autowire="byName"根据其名字去查找
package com.cjh.ioc.web; import java.util.ArrayList; import java.util.List; import com.cjh.ioc.biz.UserBiz; import com.cjh.ioc.biz.impl.UserBizImpl1; /** * 弊端: * 当需求变化非常快的时候,不变于维护,因为维护的权利是属于程序员的 * * spring的ioc就是解决这一个问题的 * 将维护代码的权利由程序员转交给spring容器来完成 * * 1、spring管理Bean的方式(注入方式) * set注入 * 基本数据类型 * 引用数据类型 * 构造注入 * 自动装配 * @author dell * */ public class UserAction { private UserBiz biz ; private int uid; private String uname; private List<String> hobby = new ArrayList<String>(); public int getUid() { return uid; } public void setUid(int uid) { this.uid = uid; } public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } public UserBiz getBiz() { return biz; } public void setBiz(UserBiz biz) { this.biz = biz; } public List<String> getHobby() { return hobby; } public void setHobby(List<String> hobby) { this.hobby = hobby; } public UserAction(int uid, String uname) { super(); this.uid = uid; this.uname = uname; } public UserAction() { super(); // TODO Auto-generated constructor stub } /** * 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() { biz.read(); } }
配置spring-context.xml文件然后在dome1调用:
<?xml version="1.0" encoding="UTF-8"?> <beans 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" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" default-autowire="byName" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"> <bean id="biz" class="com.cjh.ioc.biz.impl.UserBizImpl1"></bean> <bean id="biz2" class="com.cjh.ioc.biz.impl.UserBizImpl2"></bean> <bean id="userAction" class="com.cjh.ioc.web.UserAction"> <!-- set注入 --><!-- <property name="uid" value="12"></property> <property name="uname" value="zs"></property> --> <!-- 自动装配 --> <property name="biz" ref="biz"></property> <!-- 构造注入 --> <constructor-arg name="uid" value="22"></constructor-arg> <constructor-arg name="uname" value="ls"></constructor-arg> <property name="hobby"> <list> <value>rap</value> <value>123</value> </list> </property> </bean> </beans>
userBiz接口:
public interface UserBiz { public void read(); }
实现类:
UserBizImpl1:
public class UserBizImpl1 implements UserBiz{ @Override public void read() { // TODO Auto-generated method stub System.out.println("死记硬背!!!"); } }
UserBizImpl2:
public class UserBizImpl2 implements UserBiz{ @Override public void read() { // TODO Auto-generated method stub System.out.println("举一反三!!"); } }
测试 Domo1:
public class Demo1 { public static void main(String[] args) { // UserAction action=new UserAction(); // action.test3(); ApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml"); UserAction bean = (UserAction)context.getBean("userAction"); bean.test3(); } }
打印结果是死记硬背,因为UserBbiz对应的是接口是UserBizImpl1。
tomcat管理spring
UsersServlet
package com.cjh.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.cjh.ioc.web.UserAction; @WebServlet("/user") public class UsersServlet extends HttpServlet{ private static final long serialVersionUID = 1L; @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 { // TODO Auto-generated method stub ServletContext servletContext = req.getServletContext(); ApplicationContext springContext =(ApplicationContext)servletContext.getAttribute("SPRING_CONTEXT_KEY"); UserAction bean = (UserAction)springContext.getBean("userAction"); bean.test3(); } }
SpringLoadListener:
package com.cjh.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; /** * 如何将spring的上下文交给tomcat上下文进行管理 * 首先spring上下文为什么Tomcat? * 分析:目前工程中的所有Javabean都交给了spring进行管理,那么浏览器发送请求,请求的是Tomcat,由 * Tomcat来处理请求,Tomcat处理请求一般来说都要访问数据库,数据库是由dao层访问的,Dao层的实体类 * 又是交给了spring的上下文,那么意味着,Tomcat要处理请求,必须拿到spring的上下文,才能够拿到Dao * 层的javabean * @author dell * */ //监听器 @WebListener public class SpringLoadListener implements ServletContextListener { //spring.xxx.xml文件地址 private String springXmlLocation=""; @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("监听了Tomcat的启动。。。。"); //tomcat上下文 ServletContext servletContext = sce.getServletContext(); //拿到Tomcat上下文的初始化参数 springXmlLocation = servletContext.getInitParameter("springXmlLocation"); if(null == springXmlLocation || "".equals(springXmlLocation)) { springXmlLocation = "/spring-context.xml"; } System.out.println("springXmlLocation:"+springXmlLocation); //spring上下文 ApplicationContext springContext = new ClassPathXmlApplicationContext(springXmlLocation); servletContext.setAttribute("SPRING_CONTEXT_KEY", springContext); } }
web.xml
更改web.xml里面的名字路径
在选择你想要的xml
<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>