Spring 控制反转

  1. 具体内容

    Spring 开发框架之中有几个概念DI&IOC、AOP。那么要想理解Spring就必须首先理解控制反转的核心意义是什么?

    对于IOC来讲如果直接进行文字的描述,听起来会很麻烦。下面直接通过一套具体案例来分析什么IOC的核心本质。

    1. IOC分析场景

    实际上这样的操作过程就属于最初的开发阶段模式。如果换到程序的开发之中,那么可能最直白的做法就相当于是使用new来进行对象的产生。


package cn.wnh.service;

public interface IMessageService {

public String getInfo() ;

}


package cn.wnh.service.impl;

import cn.wnh.service.IMessageService;

public
class MessageServiceImpl implements IMessageService {

@Override

public String getInfo() {

return
"www.mldn.cn";

}

}

对于开发者来讲,最简单的使用形式就是直接利用关键字new实例化对象。


package cn.wnh.test;

import cn.wnh.service.IMessageService;

import cn.wnh.service.impl.MessageServiceImpl;

public
class TestMessage {

public
static
void main(String[] args) {

IMessageService msg=new MessageServiceImpl();

System.out.println(msg.getInfo());;

}

}

如果把TestMessage类比喻为一个出差员工,那么整个的处理过程中该员工必然要自己处理一切的可能出现的事务;

在整个的代码编写之中的确可以完成自己所需要描述的功能,但是会带来一个严重的问题:耦合度加深,因为在java中所有的开发里面,new是造成代码耦合度关键的元凶。

所以后来发现,如果继续这样的开发模式下去,整个代码将变为一潭死水。

这个时候应该引入一个专门负责具体操作的代理公司完成开发,这样就避免了程序员直接使用new来实例化对象了,就相当于提供了一个工厂的模型。如下图所

示:


package cn.wnh.factory;

import cn.wnh.service.IMessageService;

public
class ServiceFactory {

public
static IMessageService getInstance(String className){

IMessageService msg=null;

try{

msg=(IMessageService)Class.forName(className).newInstance();

}catch(Exception e){

e.printStackTrace();

}

return
msg;

}

}

用户只需要关注这个代理公司即可,就等于说程序员只需要传递一个完整的类名称给工厂即可。实例化交个工厂去完成。


package cn.wnh.test;

import cn.wnh.factory.ServiceFactory;

import cn.wnh.service.IMessageService;

import
cn.wnh.service.impl.MessageServiceImpl;

public
class TestMessage {

public
static
void main(String[] args) {

//IMessageService msg=new MessageServiceImpl();

IMessageService msg=ServiceFactory.getInstance("cn.wnh.service.impl.MessageImpl");

System.out.println(msg.getInfo());

}

}

通过工厂类取得了指定对象的实例,看似一切都很好,但是新的问题出现了:

所有的开发者都需要去关注工厂类;

所有的调用都必须明确的找到工厂类。

二、搭建Spring开发环境

本次将直接使用maven来进行Spring开发环境的搭建。同时本次所有的开发包都已经保存在了nexus私服上。

  1. 建立一个Mavenue的项目,mavenspring,搭建完成后需要配置与Spring有关的开发包。编辑pom.xml文件:

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.12</version>

</dependency>

<dependency>

<groupId>commons-logging</groupId>

<artifactId>commons-logging</artifactId>

<version>1.1.3</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<version>1.7.21</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

<version>1.7.21</version>

</dependency>

<dependency>

<groupId>javax</groupId>

<artifactId>javaee-api</artifactId>

<version>7.0</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>org.glassfish.web</groupId>

<artifactId>javax.servlet.jsp.jstl</artifactId>

<version>1.2.2</version>

</dependency>

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>jstl</artifactId>

<version>1.2</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-core</artifactId>

<version>4.3.3.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-beans</artifactId>

<version>4.3.3.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-tx</artifactId>

<version>4.3.3.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context</artifactId>

<version>4.3.3.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context-support</artifactId>

<version>4.3.3.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-web</artifactId>

<version>4.3.3.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-webmvc</artifactId>

<version>4.3.3.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-aop</artifactId>

<version>4.3.3.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-aspects</artifactId>

<version>4.3.3.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-jdbc</artifactId>

<version>4.3.3.RELEASE</version>

</dependency>

<dependency>

<groupId>c3p0</groupId>

<artifactId>c3p0</artifactId>

<version>0.9.1.2</version>

</dependency>

<dependency>

<groupId>com.mchange</groupId>

<artifactId>mchange-commons-java</artifactId>

<version>0.2.12</version>

</dependency>

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>5.1.25</version>

</dependency>

</dependencies>

  1. 如果要想实现Spring的编写需要有一个核心配置文件:applicationContext.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:p=http://www.springframework.org/schema/p

xmlns:context="http://www.springframework.org/schema/context"

xmlns:mvc="http://www.springframework.org/schema/mvc"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-4.1.xsd

http://www.springframework.org/schema/mvc

http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-4.1.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-4.1.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-4.1.xsd">

</beans>

  1. 实现Spring基础配置

    在整个的开发过程之中,首先只能够通过代码来感受一下Spring基础配置,如果你需要感受到Spring完整的优点更多的学习。

    1. 之前已经实现了基础的接口和实现类,现在在此基础上修改applicationContext.xml配置文件,加入一下信息:

    <bean id="msg" class="cn.mldn.service.impl.MessageServiceImpl"/>

    1. 在测试类中编写程序代码:

      ·Spring是一个容器所以需要先模拟该容器的启动,这里面需要使用一些Spring直接的类;

      ·要通过资源文件取得IMessageService接口对象;


package cn.wnh.test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.wnh.service.IMessageService;

public
class TestMessage {

public
static
void main(String[] args) {

//IMessageService msg=new MessageServiceImpl();

//IMessageService msg=ServiceFactory.getInstance("cn.wnh.service.impl.MessageImpl");

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

IMessageService msgService = ctx.getBean("msg",IMessageService.class) ;

System.out.println(msgService.getInfo());

}

}

3、如果说现在使用了eclipse直接开发,但是此网络比较慢的话,这样的话程序对于xml文件的验证速度会很慢,所以为了了解这个文件,可以采用如下步骤完成:

·将所需要的xsd的文件下载下来

·建议关闭xml验证操作:在首选项中选择 "validation"配置,取消xml的验证规则:

然后将所需要的*.xsd的格式文件配置都项目里:"首选项",进入"xml"配置,添加"xml Catalog",选择"用户特定实体",然后将下载好的*.xsd文件一一添加进去,添加时请注意选择key Type 为Schema location;

为了保证正确,建议Eclipse重新启动。

4、都已经涉及到了开发框架,且开发框架以及配置好了一个常用的日志组件:log4j、slf4j。建议在 "/src/main/resources"中拷贝一个log4j.properties文件,果不配置日志文件,那么所有的错误信息都会看不到。

5、配置好了日志文件,以后进行代码测试时就可以不再使用System.out了,应该使用日志文件的形式输出;

·配置要使用的开发包,别导错了:


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

取得Logger类对象后,通过这个对象进行输出。输出日志有如下几种形式:

·info():表示普通的信息输出;

·warn():表示警告信息,但是不致命;

·error():表示出现异常信息;

·debug():表示调试信息;

通过以上的配置就可以发现在整个的Spring里面对于对象的产生完全由Spring自己来进行维护,这样的开发是有好处的,避免了关键字new。


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.wnh.service.IMessageService;

public
class TestMessage {

public
static
void main(String[] args) {

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

IMessageService msgService = ctx.getBean("msg",IMessageService.class) ;

//IMessageService msg=new MessageServiceImpl();

//IMessageService msg=ServiceFactory.getInstance("cn.wnh.service.impl.MessageImpl");

//System.out.println(msgService.getInfo());

Logger log=LoggerFactory.getLogger(TestMessage.class);

log.info(msgService.getInfo());

log.error(msgService.getInfo());

log.warn(msgService.getInfo());

}

}

6、既然都使用到maven开发,那么对于代码的测试就不要再去编写测试类进行测试了,应该使用junit进行测试;

在pom.xml中配置一下信息即可;


<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.12</version>

</dependency>

使用junit类测试:


public
class TestMessage {

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

@Test

public
void TestGetInfo(){

IMessageService msgservice=ctx.getBean("msg",IMessageService.class);

//输出MessageService类中getInfo()里的内容;

Logger.getLogger(TestMessage.class).info(msgservice.getInfo());

//比较MessageService类中getInfo()里的输出信息与"www.wnh.cn"进行比较",如果相等则输出;

TestCase.assertEquals(msgService.getInfo(),"www.wnh.cn");

}

总结:控制反转简单的说就是通过Spring容器的applicationContext.xml文件进行简单的配置"<bean id="msg" class="cn.mldn.service.impl.MessageServiceImpl"/>",就可以轻松实现对类的实例化,实例化名称就相当于配置文件中的id;然后便可以在测试类中取得容器对象"ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml")",通过容器对象便可以取得类对象"IMessageService msgservice=ctx.getBean("msg",IMessageService.class)"然后便可以取得类中的内容,这样的一个过程,就称为控制反转;

总的来说,Spring 的确是提供了方便的对象管理,但是其开发的过程以及所需要的开发包是非常强大的,上只是实现了一个接口对象的注入处理,以后还可能牵扯到更多的对象的注入过程。

时间: 2024-11-10 12:32:03

Spring 控制反转的相关文章

Spring控制反转(IOC)和依赖注入(DI),再记不住就去出家!

每次看完spring的东西感觉都理解了,但是过了一段时间就忘,可能是不常用吧,也是没理解好,这次记下来. 拿ssh框架中的action,service,dao这三层举例: 控制反转:完成一个更新用户信息的业务操作,首先在action中需要service对象来处理逻辑操作,但是在action中我们并没有进行类似new Service()的操作,因为spring容器已经帮我们完成了这 样的创建被调用者对象的工作,因此称为控制翻转.这样命名这个技术可能还是有点晦涩,参考 http://blog.csd

spring——控制反转简单例子

spring框架是一个开源的轻量级的基于IOC与AOP核心技术的容器框架,主要是解决企业的复杂操作实现. 那IOC与AOP,到底如何解释呢,在看spring视频中,两个专业术语一定必须要懂得. IOC:inverse of Control:控制反转.意思是程序中的之间的关系,不用代码控制,而完全是由容器来控制.在运行阶段,容器会根据配置信息直接把他们的关系注入到组件中.同样,这也是依赖注入的含义.依赖注入和控制反转其实是一个概念.只不过强调的不同而已,依赖注入强调关系的注入是由容器在运行时完成,

spring——控制反转

像前面博客中提到struts框架,Hibernate框架似的,spring同样也是一个开源的框架.使用框架的的优势在于分层结构,每层有相应的框架,减少开发工作量,减少组件之间的耦合.struts框架应用web层,Hibernate框架应用持久层,spring应用两者之间. 我觉得,框架是出于聪明的赖人之手.聪明是说他们开发封装每层框架,把复杂的操作全部封装在框架中.而赖人是说他所有复杂的操作实现全部交给计算机来实现,减少人们的开发工作量,把工作的注意力集中在业务逻辑上. 那我们来介绍一下stru

Spring控制反转的最简单说明

现有角色如下: 一个接口Interface,两个接口实现类InstatnceA.InstanceB,一个调用类User. 已有代码如下: User类中实例化了一个InstatnceA对象,代码如:Interface interface = new InstanceA(); 现欲修改如下: 现在想把实例化对象改为InstatnceB而不要实例化InstanceA了,为此我们需要修改代码为:Interface interface = new InstanceB(); 现在的控制是: User控制实例

Spring控制反转(IOC)

SpringIOC Spring的控制反转:把对象的创建.初始化.销毁等工作交给spring容器来做.由spring容器控制对象的生命周期. 步骤:两个步骤,步骤1有两个加载配置文件形式,通过加载配置文件实例化容器 IOC面向接口的强大 Spring容器内部对象 创建对象的方式 无参构造函数 <bean id="personService" class="cn.itcast.bean.impl.PersonServiceImpl"/> 静态工厂 工厂方法

对spring控制反转以及依赖注入的理解

一.说到依赖注入(控制反转),先要理解什么是依赖. Spring 把相互协作的关系称为依赖关系.假如 A 组件调用了 B 组件的方法,我们可称A 组件依赖于 B 组件. 二.什么是依赖注入. 在传统的程序设计过程中,通常由调用者来创建被调用者的实例. 在依赖注入的模式下,创建被调用者的工作不再由调用者来完成,因此称为控制反转:创建被调用者实例的工作通常由Spring 容器来完成,然后注入给调用者,因此也称为依赖注入. 自己理解:即一句话,由spring容器来控制组件A的调用的具体对象B.组件A依

Spring控制反转IOC

spring的控制反转(IOC)思想,对象实例不再是由调用者来创建,改为spring容器来创建.spring容器会负责控制程序之间的关系,不再由程序代码直接控制,控制权由应用的代码转向了外部容器,所谓控制反转.spring有两个ioc容器,这里我用的是ApplicationContext. 以一个类为例: public class UserService { public void addUser() { System.out.println("user add"); } } 在xml

尚学堂Spring视频教程(二):Spring控制反转

用Spring来实现IOC 在上节中我们自定义了一个接口BeanFactory和类ClassPathXmlApplicationContext来模拟Spring,其实它们在Spring中确实是存在的,下面我们具体来看看Spring的控制反转是如何操作的 其他代码一样,只是配置文件和单元测试的代码有点不同,注意引用其他bean配置的是"ref"属性 <?xml version="1.0" encoding="UTF-8"?> <b

Spring控制反转和依赖注入

(1)为什么使用控制反转和依赖注入 调用者不用去关心被调用者的实现,不需要调用者亲自创建被调用者的实例,这些操作都交给框架去完成. 这种设计思想就是控制反转(Inversion of Control, IoC),同时,它还有另外一个名字就是依赖注入(Dependency Injection, DI). (2)什么是控制反转和依赖注入 控制反转(IoC)是将由程序控制的"对象间的依赖关系"转交给IoC容器来进行控制,被调用者的实例创建工作不再由调用者来完 成.通过控制反转,可以实现由外部