springMVC学习(什么是IOC)

接下来这段时间,我将会写一个关于springMVC的博客专栏,首先看看百度百科上是怎么定义springMVC的。

Spring是一个开源框架,Spring是于2003
年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert
One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring的核心是控制反转IoC)和面向切面(AOP)。简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架。

先来看看spring官方为我们提供的一张图片:

是不是看的云里雾里的,什么是IOC,什么又是AOP还有什么又是springMVC,接下来的这个系列的博客,我将会带大家逐步学习spring。我们首先来学习spring 的ioc模块吧。

ioc又名控制反转,说白了就是把对象的创建,销毁以及初始化等一系列操作交给spring容器来处理,由spring来控制对象的声明周期。举个栗子:我们现在写了很多java类,然后书写一个spring的配置文件,将这些类交给spring容器来处理,此时这些对象的初始化以及销毁就会由spring来管理,如果我们需要使用对象的话,只需要遵守spring中的规范来书写代码,就可以得到指定的对象,对于应该遵守什么样的规范,这个以后我们在详细来探讨。这也就是我们ioc(控制反转的来历)。即将对象交给spring来控制管理。那么ioc带给我们的优势又有那些呢??大家仔细想想,到现在我们如果需要用到某一个类对象,只能通过手动new出来,那有人可能会说了,我不是可以使用工厂模式吗?注意:工厂模式只是提供给我们创建对象的一个简单调用,其内部同样是new一个我们需要的对象,但是如果使用spring以后,我们只需要在spring的配置文件里边配置好需要有spring来管理的类,具体的该对象的创建管理等都是由spring来做的。废话不多说,我们先来看一个例子:

我们新建一个java工程,将spring需要的核心jar包拷贝进去。

1.dist/spring.jar

2.lib/jakarta-commons/commons-logging.jar

这两个就是spring需要的核心jar文件,接下来我们新建一个类HelloIoc.java

package com.test.ioc;
public class HelloIoc {

	public void helloIoc() {
		System.out.println("hello ioc first");
	}
}

接下来,给大家演示用spring来管理HelloIoc这个类。首先,我新建一个applicationContext.xml文件:内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
<span style="white-space:pre">	</span>xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<span style="white-space:pre">	</span>xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<span style="white-space:pre">	</span><bean id="helloIoc" class="com.test.ioc.HelloIoc">
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span></bean>

</beans>

那么,有人可能会问,这么多的东西我怎么记得住呢,不用急,我也是在官方文档中找到的。可以看到,这里的根节点的名称叫做beans,即包含了很多其他的bean,在这里一个bean就是一个具体的类。

说明一下:这里bean中的id就是唯一标识一个bean的,一般是类名称的第一个字母小写。class顾名思义就是这个类的全类名,大家写的时候,可以按住ctrl键然后点击,如果可以进入,说明class的值是正确的。

spring容器到现在已经创建好了,现在我们写一个测试类,加载spring容器,将HelloIoc从容器中拿出来。

package com.test.ioc;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloIocTest {

	public static void main(String[] args) {

		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/test/ioc/applicationContext.xml");
		HelloIoc helloIoc = (HelloIoc) applicationContext.getBean("helloIoc");
		helloIoc.helloIoc();
	}
}

此时运行我们的main方法,会发现helloIoc()方法已经被执行了,发现我们是没有new HelloIoc这样的方式来创建,而是通过spring容器来为我们创建该对象的。这里需要注意,ApplicationContext就是我们的上下文,通过它来加载配置文件的,然后通过

applicationContext.getBean("helloIoc");来获取我们的实体类,这里getBean中的参数就是我们在spring配置文件中配置的bean的id。

接下来我们在HelloIoc中加上构造方法,如下:

package com.test.ioc;

public class HelloIoc {

	public void helloIoc() {
		System.out.println("hello ioc first");
	}

	public HelloIoc() {
		super();
		System.out.println("HelloIoc has been init");
	}
}

然后两次获取该HelloIoc的对象,如下:

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/test/ioc/applicationContext.xml");
HelloIoc helloIoc = (HelloIoc) applicationContext.getBean("helloIoc");
HelloIoc helloIoc2 = (HelloIoc) applicationContext.getBean("helloIoc");
System.out.println(helloIoc);
System.out.println(helloIoc2);

此时,控制台打印结果是这样的:

HelloIoc has been init

[email protected]

[email protected]

可以发现虽然我们得到了两个HelloIoc对象,可是这两个对象是一样的,同时发现构造方法也执行了一次,这就充分说明spring默认为我们创建对象是用的单例模式。可是这里有一个问题,就是单例模式的时候,会出现线程安全问题,比如我现在在为HelloIoc中添加一个String name变量,并且提供get,set方法:

package com.test.ioc;

public class HelloIoc {
	private String name = "";
	public void helloIoc() {
		System.out.println("hello ioc first");
	}

	public HelloIoc() {
		super();
		System.out.println("HelloIoc has been init");
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

然后将测试类的代码修改如下:

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/test/ioc/applicationContext.xml");
HelloIoc helloIoc = (HelloIoc) applicationContext.getBean("helloIoc");
HelloIoc helloIoc2 = (HelloIoc) applicationContext.getBean("helloIoc");
helloIoc.setName("xiaoming");
helloIoc2.setName("test");
System.out.println(helloIoc);
System.out.println(helloIoc2);
System.out.println(helloIoc.getName());
System.out.println(helloIoc2.getName());

此时打印的结果如下:

HelloIoc has been init

[email protected]

[email protected]

test

test

根据结果我们可以看出现在由于是单例模式,所以出现了helloIoc2将helloIoc的name变量修改了。那么如何避免该问题的出现呢,其实在配置文件中添加这样一句话"scope="prototype""就可以取消默认的单例模式创建该bean了。如下:

<bean id="helloIoc" class="com.test.ioc.HelloIoc" scope="prototype">

</bean>

此时的打印结果如下:

HelloIoc has been init

HelloIoc has been init

[email protected]

[email protected]

xiaoming

test

可以发现这个时候,spring为我们创建了两个不同的对象。

这个时候我们已经利用了spring容器来创建我们的对象,现在,我们来演示对象的初始化和销毁的操作。

在spring配置文件中,bean的配置文件中,spring已经为我们提供了对象的初始化和销毁的设置方法:init-method="" destroy-method=""可以看到这样的设置就可以了。接下来我新建一个类,用来演示spring操作对象中初始化和销毁的行为。

package com.test.ioc;

public class HelloIocInitDes {

	public HelloIocInitDes() {
		super();
		System.out.println("HelloIocInitDes runs..");
	}

	public void init() {
		System.out.println("init runs ...");
	}

	public void destroy() {
		System.out.println("destroy runs ...");
	}
}

记住只要我们需要让spring来管理该对象,那么必须在spring的配置文件中配置该bean,这里我加上初始化和销毁方法的设置。

<bean id="helloIocInitDes" class="com.test.ioc.HelloIocInitDes" init-method="init" destroy-method="destroy"></bean>

然后新建一个HelloIocInitDesTest.java来测试初始化和销毁的操作。代码如下:

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/test/ioc/applicationContext.xml");
HelloIocInitDes helloIocInitDes = (HelloIocInitDes) applicationContext.getBean("helloIocInitDes");

此时运行该HelloIocInitDesTest.java的main方法,结果如下:

HelloIocInitDes runs..

init runs ...

可以看到init方法是在构造方法之后执行的,可是我们发现执行了init方法,而destroy方法并没有执行,这是怎么回事,因为spring还没有准备销毁我们的对象,我们现在模拟关闭spring容器,来让destroy方法得到执行。

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/test/ioc/applicationContext.xml");
HelloIocInitDes helloIocInitDes = (HelloIocInitDes) applicationContext.getBean("helloIocInitDes");
ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;
context.close();

此时打印如下:

可以发现此时destroy方法得到了执行。

可是,如果此时我在HelloIocInitDes中的bean配置文件中加上这样一句话:scope="prototype",即不是用默认单例模式创建对象,会发想destroy-method并没有执行。即使我关闭了spring容器。

总结一下:init-method="init"方法是在构造方法之后由spring容器执行的,我们可以用他来做一些初始化的操作,在destroy-method中做关闭资源等操作,如果该bean不是默认的单例模式创建,此时将不会执行destroy-method。那么关闭资源等操作,将由人为来完成。

那么spring又是什么时候帮我们创建bean对象的呢??在bean的配置文件中有这么一句配置:lazy-init="",该配置存在两个值:

lazy-init="default" 和lazy-init="true"默认是false。这里,当我lazy-init="default"的时候,即spring容器加载进内存以后就会创建该bean对象,如果lazy-init="true",那么只有在执行geBean("")方法的时候才会创建该bean对象。

大家注意一下,目前我们所采用的spring容器中的所有的bean的配置都是采用构造函数来创建bean对象的,接下来我介绍一种利用静态工厂的方式来创建bean对象。首先我新建一个HelloIocFactory.java里边定义一个getInstance方法,用来创建HelloIoc对象。

package com.test.ioc;

public class HelloIocFactory {

	public static HelloIoc getInstance() {
		return new HelloIoc();
	}
}

然后再bean中这样配置即可:

<bean id="helloIoc2" class="com.test.ioc.HelloIocFactory"
		factory-method="getInstance"></bean>

此时如果想要到的HelloIoc对象,只需要像往常那样通过getBean("")方法调用就行了。

今天的springIOC就到这里吧,下一篇我会写一个spring依赖注入的博文,希望大家喜欢。

源码下载

时间: 2024-10-07 20:44:32

springMVC学习(什么是IOC)的相关文章

springmvc学习总结(二) -- maven+springmvc+spring+mybatis+mysql详细搭建整合过程讲解

@[email protected] 写在最前 之前分享过下面这几篇: mybatis学习笔记(五) -- maven+spring+mybatis从零开始搭建整合详细过程(上)(附demo和搭建过程遇到的问题解决方法) mybatis学习笔记(六) -- maven+spring+mybatis从零开始搭建整合详细过程(下) springmvc学习笔记(一) -- 从零搭建,基础入门 这一篇,在这些练习的基础上,将它们整合在一起! 搭建步骤如下 一.新建maven项目,配置环境,测试是否配置成

SpringMVC学习笔记(二): 日常使用功能

前提: 1.web.xml 和spring-mvc核心配置如:SpringMVC学习笔记(一): 基础知识中注解实现. 2.类的@RequestMapping(value="/annotationController") 3.spring-mvc 推荐使用注解实现. 一.数据的接收 (一)URL参数数据的接收 1.使用 HttpServletRequest 获取参数 <span style="font-size:18px;"><span style

SpringMVC学习系列(12) 完结篇 之 基于Hibernate+Spring+Spring MVC+Bootstrap的管理系统实现

到这里已经写到第12篇了,前11篇基本上把Spring MVC主要的内容都讲了,现在就直接上一个项目吧,希望能对有需要的朋友有一些帮助. 一.首先看一下项目结构: InfrastructureProjects:是抽取出的基础项目,主要封装了一些通用的操作. SpringMVC3Demo:就是管理系统所在的项目. WeiXinAPI:是之前做微信管理平台测试时封装一些操作,如果不需要把该项目移除即可. 注:项目的前端UI框架用的是国外的一个基于Bootstrap框架的开发的Demo,如不需要替换为

SpringMVC学习系列(10) 之 异常处理

在项目中如何处理出现的异常,在每个可能出现异常的地方都写代码捕捉异常?这显然是不合理的,当项目越来越大是也是不可维护的.那么如何保证我们处理异常的代码精简且便于维护呢?这就是本篇要讲的内容->异常处理. 在Spring MVC中我们可以通过以下2中途径来对异常进行集中处理: 一.继承HandlerExceptionResolver接口实现自己的处理方法,如: public class MyHandlerExceptionResolver implements HandlerExceptionRe

史上最全的SpringMVC学习笔记

SpringMVC学习笔记---- 一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的jar包. 2.添加Web.xml配置文件中关于SpringMVC的配置 <!--configure the setting of springmvcDispatcherServlet and configure the mapping--> <servlet> <servlet-name>springmvc</servlet

springMvc学习笔记01

此系列文章记录学习springMvc的过程: 第一想法是到spring官网下载相关jar, 查看了一下,点了目录链接,然而并没有jar的下载链接,还以为自己看错了,又特地准备了翻译工具,结果还是没有发现jar和源码的下载链接,我郁闷了,why, 网友们说spring的jar和示例在github上,看了官网的文档介绍,觉得不太好,下面会贴出我学习时用到的链接,ps:至今我还认为可能是我太笨了没找到~~~ 1.下载jar包 http://repo.spring.io/libs-release-loc

SpringMVC学习系列(11) 之 表单标签

本篇我们来学习Spring MVC表单标签的使用,借助于Spring MVC提供的表单标签可以让我们在视图上展示WebModel中的数据更加轻松. 一.首先我们先做一个简单了例子来对Spring MVC表单表单标签的使用有一个大致的印象,然后再结合例子对各个标签介绍一下如何使用. 1.首先,在com.demo.web.models包中添加一个模型TagsModel内容如下: package com.demo.web.models; import java.util.List; import ja

springmvc学习笔记--REST API的异常处理

前言: 最近使用springmvc写了不少rest api, 觉得真是一个好框架. 之前描述的几篇关于rest api的文章, 其实还是不够完善. 比如当遇到参数缺失, 类型不匹配的情况时, 直接抛出异常, 返回的内容是500+的错误页面, 而不是json内容, 这让移动端的调用方很难处理. 本文主要讲述对于rest api, springmvc对异常的解决处理方案. 系列整理: springmvc学习笔记系列的文章目录: • idea创建springmvc项目 • 面向移动端的REST API

SpringMVC学习系列(9) 之 实现注解式权限验证

对大部分系统来说都需要权限管理来决定不同用户可以看到哪些内容,那么如何在Spring MVC中实现权限验证呢?当然我们可以继续使用servlet中的过滤器Filter来实现.但借助于Spring MVC中的action拦截器我们可以实现注解式的权限验证. 一.首先介绍一下action拦截器: HandlerInterceptor是Spring MVC为我们提供的拦截器接口,来让我们实现自己的处理逻辑,HandlerInterceptor 的内容如下: public interface Handl