`

spring依赖注入DI(即控制反转IOC)的一个小实例

阅读更多

spring的核心是IOC(控制反转)和AOP(面向切面)

 

今天先来学习下IOC。IOC另一种说法是依赖注入(DI),它能够通过三种注入方式来将工程中耦合性很高的类进行不完全解耦。

三种注入方式:⑴构造器注入 ⑵接口注入 ⑶setter方法注入!

 

一般的话都会使用setter方法注入的方式来进行编程;下面来讲解一下spring依赖注入的原理(我的理解)

 

在java中类与类之间的关系是相互调用的关系,所以如果一个类需要调用另一个类的方法就需要创建出另一个类的对象,通过对象来调用另一个类的方法,比如这样:

   一个狗的类,拥有叫和跳两种方法:

package com.ioc.test;

import java.util.jar.Attributes.Name;
public class Dog {
	private String name;
	public void bark(String name ) {
		System.out.println(name+"叫了一下!");
	}
	public void jump(String name) {
		System.out.println(name+"跳了一下!");
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getSize() {
		return size;
	}
	public void setSize(int size) {
		this.size = size;
	}
}
  而人会命令狗做一些事情,比如让狗叫或者让狗跳之类的,

 

 

 

    定义一个person类,拥有让狗叫,让狗跳两种方法。在两种方法中传入Dog的实例对象。

package com.ioc.test;
public class Person {
	private String name;
	
	//向方法中传入Dog对象
	public void holdDogBark(com.ioc.test.Dog dog){
		//调用dog对象的bark方法 并使用传入的dog对象的getName方法获得dog的name属性 
                //传入bark方法内
		dog.bark(dog.getName());
	}
	public void holdDogJump(Dog dog){
		dog.jump(dog.getName());
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

}
   

 

 

   写一个拥有main函数的测试类:

   在该类中创建两个类的对象并调用Person对象两个方法 ,在方法中传入Dog对象,这样就完成了一次            Person类与Dog类之间的操作。

 

package com.ioc.test;

public class PersonManager {

		public static  void main ( String args[]){
			Dog dog =new Dog();
			dog.setName("小白");
			Dog dog2=new Dog();
			dog2.setName("小黑");
			Person person=new Person();
			person.holdDogBark(dog);
			person.holdDogJump(dog);
			person.holdDogBark(dog2);
			person.holdDogJump(dog2);
		}
}

 

   但是如果这样的话会让代码拥有过高的耦合度,非常的不利于后期的维护与开发。 比如有一天Dog类中会      多一个方法run其中又调用了jump方法

   而Person类中新增了一个letDogRun方法并且其中用到了holdDogJump方法 ,就需要将两个类的代码同时    改变。

   其实只有这两个类的话还是看不太出来代码耦合度高会带来不便之处,但是如果调用Dog类的类很多的话      而且还有很多使用Person类方法的类,这样你在每个使用过jump和holdDogJump方法的类中都需要进行修    改。这会花费你大量的精力与时间。

 

而在spring中完成上面的操作会将两个类的关系从相互调用变成依赖注入。而且注入过程中完全不需要你去建立实体类。下面就是步骤

 ⒈首先导入spring的jar包到所建立的工程中

   我这里导入了spring框架的所有jar包如图: 


    值得注意的是被红线圈住的包 ,我刚开始导入的时候并没有将它导入,之后在测试的时候报了一个错

     NoClassDefFoundError,下面是错误信息:

Exception in thread "main" java.lang.NoClassDefFoundError: 
org/apache/commons/logging/LogFactory
	at org.springframework.context.support.AbstractApplicationContext.<init>
(AbstractApplicationContext.java:158)
	at org.springframework.context.support.AbstractApplicationContext.<init>
(AbstractApplicationContext.java:222)
	at org.springframework.context.support.AbstractRefreshableApplicationContext.<init>
(AbstractRefreshableApplicationContext.java:88)
	at org.springframework.context.support.AbstractRefreshableConfigApplicationContext.
<init>(AbstractRefreshableConfigApplicationContext.java:58)
	at org.springframework.context.support.AbstractXmlApplicationContext.<init>
(AbstractXmlApplicationContext.java:61)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>
(ClassPathXmlApplicationContext.java:136)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>
(ClassPathXmlApplicationContext.java:83)
	at com.ioc.userioc.test.PersongUseDogTest.main(PersongUseDogTest.java:13)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 8 more
    我从网上搜了一下通过他的博客知道了缺少该包,导入该包后异常果然消失,非常感谢这个博主!
    如果想要了解NoClassDefFoundError和ClassNotfoundException的区别的话可以去这个博客看下。
    言归正传,

    ⒉创建两个接口interface Person和interface Dog,在里面定义需要的方法:

    Person.java

package com.ioc.userioc.interfac;

import javax.xml.ws.Holder;

	//接口person
public interface Person {
	//定义了两个无返回类型的方法
		void holdDogBark();
		void holdDogJump();

}

    Dog.java

package com.ioc.userioc.interfac;


//定义一个Dog接口
public interface Dog {
	
	//定义两个方法bark 和jump 返回类型均为string
	String bark();
	String jump();
	
}

   ⒊创建接口的实现类

 

    ShortDog.java

package com.ioc.userioc.impl;

import com.ioc.userioc.interfac.Dog;

//Dog接口的实现类
public class ShortDog implements Dog{
	
	//实现两个Dog中定义的方法
	@Override
	public String bark() {
		System.out.println("小狗叫了一下!");
		return "小狗叫了一下!";
	}
	@Override
	public String jump() {
		System.out.println("小狗跳了一下!");
		return "小狗跳了一下!";
	}
}

    Chinese.java

package com.ioc.userioc.impl;

import com.ioc.userioc.interfac.Dog;
import com.ioc.userioc.interfac.Person;

//person的实现类
public class Chinese	implements Person {
	//创建的是一个接口的实例吗?  这并不是一个实例  
	//实例会在你调用本类中需要这个变量的方法时由spring根据applicationContext.xml文件创
        //建出来
	//注入的Dog类型的变量   通过setter方法注入
	private com.ioc.userioc.interfac.Dog dog;
	
	//覆盖接口person的方法 
	@Override
	public void holdDogBark() {
		System.out.println("一个人让"+dog.bark());
	}
	@Override
	public void holdDogJump() {//
		System.out.println("一个人让"+dog.jump());
	}
	//通过setter方法注入dog的实例对象
	public void setDog(Dog dog) {
		this.dog = dog;
	}
}

    ShortDogProxy.java

package com.ioc.userioc.impl;

import com.ioc.userioc.interfac.Dog;
//  代理类  在本类中重写dog接口的方法中可以添加一些日志或者是自己想要进行的一些操作
//这就是面向切面的一个用处
public class ShortDogProxy implements Dog{
	//注入的Dog类型的变量   通过setter方法注入
	private Dog dog;
	@Override
	public String bark() {
		//方法执行前的说明语句
		System.out.println("哈哈,这是dog.bark执行前");
		try{
			//这里的bark方法实际上就是applicationContext.xml文件中本类在里面定义
                        //的引用类的bark方法  引用类也必须实现Dog接口
			//因为在本类中也被注入了一个Dog 变量
		return	dog.bark();
		}finally{
			//bark方法执行后
			System.out.println("哈哈,这是dog.bark执行后");
		}
	}
	@Override
	public String jump() {
		System.out.println("哈哈,这是dog.jump执行前");
		try{
			return	dog.jump();
		}finally{
			System.out.println("哈哈,这是dog.jump执行后");
		}
	}
	public void setDog(Dog dog) {
		this.dog = dog;
	}
}

   ⒋配置applicationContext.xml文件

    applicationContext.xml

 

 

<?xml version="1.0" encoding="UTF-8"?>
<!-- spring配置文件的限制元素 ,规定了本文件会用到的标签以及格式 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans"
	xsi:schemaLocation="http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

	<!-- bean中的id是对于相应的class的标识		
		在	 -->
	<bean id="chinese" class="com.ioc.userioc.impl.Chinese">
	<!-- property标签就是属性标签  他的值就是注入到Chinese类中的实现Dog接口的类 
             在本文件中 以bean的方式定义。
             name属性为dog说明这个chinese类需要一个dog类型的类的对象,就是dog接口实现类的
             对象只要实现了dog接口的类都可以
	 -->
		<property name="dog" ref="shortdogV2"></property>
	</bean>

	<!-- 这个bean是一个代理类 他虽然实现了dog接口 但是再它重写的Dog接口方法中添加了
             除核心操作外的一些操作-->
	<!-- 面向切面编程  -->
	<bean id="shortdogV2" class="com.ioc.userioc.impl.ShortDogProxy">
		<property name="dog" ref="shortdog" />
	</bean>
	
	<!--被上面的shortdogV2所引用   -->
	<bean id="shortdog" class="com.ioc.userioc.impl.ShortDog"></bean>

</beans>

    ⒌建立测试类进行测试

 

     PersongUseDogTest.java

package com.ioc.userioc.test;

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

import com.ioc.userioc.interfac.Person;

// 测试类 测试
public class PersongUseDogTest {
public static void main(String[] args) {
	//new 出来一个根据classpath的xml文件生成的applicationContext对象
	ApplicationContext applicationContext=new ClassPathXmlApplicationContext
        ("applicationContext.xml");
	//Person是一个接口,而person是一个引用变量,person可以指向任何实现了Person接口的类,
	//而ApplicationContext的getBean方法 ,是根据xml文件中的配置和方法的参数得到一个bean 
        //对象
	//方法中的chinese应该是bean的ID而Person.class
	Person person=applicationContext.getBean("chinese", Person.class);
	//调用person的方法holdDogBark  其实就是通过applicationContext.xml得到的一个实现
        //person接口的类就是Chinese的对象
	//然后再调用这个对象的holdDogBark方法 ,在这个方法被运行时方法需要一个实现
        //Dog接口的类,这个方法会根据
	//applicationContext.xml文件来
	person.holdDogBark();
	person.holdDogJump();
	}
}

    结果

二月 24, 2017 12:35:06 下午 org.springframework.context.support.
AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.
ClassPathXmlApplicationContext@6c589e: startup date [Fri Feb 24 12:35:06 CST 2017]; 
root of context hierarchy
二月 24, 2017 12:35:06 下午 org.springframework.beans.factory.xml.
XmlBeanDefinitionReader
 loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
哈哈,这是dog.bark执行前
小狗叫了一下!
哈哈,这是dog.bark执行后
一个人让小狗叫了一下!
哈哈,这是dog.jump执行前
小狗跳了一下!
哈哈,这是dog.jump执行后
一个人让小狗跳了一下!

 

 
    总结:spring的控制反转就是当一个类需要调用其他类的方法时,通过配置到xml文件中的       一个个bean来生成所需要的对象来注入需要该对象的类的方法中,内部流程完全是spring来     做你只需要使用该类调用方法就可以了。在上面了例子中还用到了一点点的面向切面                (AOP)就是在person再调用holdDogBark方法时注入了ShortDogProxy的实例对象,先       执行了它实现Dog的方法,再将实际的工作类ShortDog类的对象注入到里面,执行                   ShortDog对象的bark方法。
 
   全都是在下的一点点见解,如有错误,欢迎指出。
 

 

 

 

 

  • 描述: 引得jar包
  • 大小: 21.2 KB
分享到:
评论

相关推荐

    springIOC控制反转 依赖注入实例

    控制反转(IOC)意味着应用程序不再直接创建对象,而是将对象的创建和管理交给一个外部容器(在Spring中就是IOC容器)。这样,开发者可以更专注于业务逻辑,而不是对象的生命周期。依赖注入(Dependency Injection,...

    Spring Ioc 注解 依赖注入

    - **依赖注入**:依赖注入是一种设计模式,通过依赖注入,一个类的对象不再负责创建其依赖的对象,而是由外部容器(Spring容器)来负责创建这些依赖并注入到需要它们的地方。 #### 三、Spring IoC容器的工作原理 ...

    Spring 控制反转 依赖注入

    **Spring 框架中的控制反转 (IoC) 和依赖注入 (DI)** 在软件开发中,控制反转(Inversion of Control,简称IoC)是一种设计原则,它将对象的创建和管理权从代码中剥离出来,转交给一个外部容器(如Spring框架)。...

    Spring框架控制反转IOC和依赖注入DI详解

    本文介绍了Spring框架中的控制反转IOC和依赖注入DI,欢迎阅读,共同学习,一起进步。 Spring框架基础参考:深入学习Spring基础 文章目录一.入门程序和IOC简介二.IOC-控制反转三.DI-依赖注入四. IOC和DI五.Spring...

    Spring依赖注入DI.zip

    在Spring框架中,DI通过控制反转(Inversion of Control,IoC)实现,也就是将对象的创建和管理权交给了Spring容器。下面我们将深入探讨Spring依赖注入的概念、工作原理以及如何在实践中应用。 1. **依赖注入概念**...

    Spring IOC 控制反转

    接下来,我们通过一个简单的示例代码来进一步理解Spring IOC控制反转的实现过程: ```java // 定义一个DAO层接口 public interface UserDao { void save(); } // DAO层接口的实现类 public class UserDaoImpl ...

    Spring——IOC(控制反转)与DI(依赖注入).docx

    Spring框架中的IOC(控制反转)和DI(依赖注入)是两种关键的设计模式,它们极大地提升了软件的可维护性和可扩展性。控制反转是一种设计思想,它改变了传统的对象创建方式,将对象的创建和管理权从应用程序自身转移...

    spring dom4j 解析 依赖DI注入 ioc 反转 反射原理

    在IT行业中,Spring框架是Java开发中的核心工具,它提供了许多功能,如依赖注入(DI)、面向切面编程(AOP)以及IoC(控制反转)。在这个话题中,我们将深入探讨Spring框架如何利用DOM4J解析XML配置文件,依赖注入...

    Spring Ioc(依赖注入)入门例子--属性注入

    Spring的核心特性之一就是它的Inversion of Control(IoC,控制反转)容器,也被称为Dependency Injection(DI,依赖注入)。这个概念是Spring框架使应用程序组件之间解耦的关键。让我们深入探讨一下Spring的IoC和...

    IOC控制反转&DI依赖注入

    而在IOC中,这种控制权被反转,对象的创建和管理交给了一个外部的容器(如Spring框架),程序员不再直接负责对象的实例化,而是通过配置文件或注解来声明对象间的依赖关系。这样,对象的生命周期和依赖关系的管理就...

    springIoc实现原理

    在IoC中,不再由对象自己去创建或查找依赖的对象,而是将这种控制权交给一个专门的容器(即Spring Ioc容器)。这样,对象只需要声明自己需要哪些依赖,而具体的获取和管理过程则由容器负责,实现了对象间的低耦合。 ...

    Spring_01_入门篇_依赖注入(控制反转)_XML

    在`Spring_01_入门篇_依赖注入(控制反转)_XML`中,我们可以看到一个或多个XML配置文件,它们定义了bean的定义,包括bean的类名、属性以及它们之间的依赖关系。例如: ```xml ``` 在这个例子中,`exampleBean`...

    控制反转(IoC)与依赖注入(DI)1

    而在IoC模式下,这种依赖关系被反转,对象A不再负责创建或管理对象B,而是由一个第三方——即IoC容器——负责创建和维护对象B,并将其注入到对象A中,使得对象A能够使用对象B。这样,对象A和对象B之间实现了解耦,...

    Springioc注入Demo

    Spring IOC(Inversion of Control,控制反转)是Spring框架的核心特性,它将对象的创建和管理权交由Spring容器来负责,从而实现了依赖倒置,增强了代码的可测试性和可维护性。DI(Dependency Injection,依赖注入)...

    Spring基础实例(依赖注入和控制反转)

    本实例主要探讨Spring框架的基础概念,包括依赖注入(Dependency Injection,简称DI)和控制反转(Inversion of Control,简称IoC)。这两个概念是Spring的核心特性,它们极大地简化了代码的维护和管理,提高了软件...

    helloIoc.zip spring ioc控制反转简单测试代码

    Spring框架的核心特性之一就是依赖注入(Dependency Injection,简称DI),它通过控制反转(Inversion of Control,简称IOC)实现。这个"helloIoc.zip"压缩包包含的是一组用于演示Spring IOC基本概念和使用的测试...

    Spring 的DI和IoC实例详解(转)

    在Java开发领域,Spring框架是应用最广泛的轻量级框架之一,它以其强大的依赖注入(Dependency Injection,简称DI)和控制反转(Inversion of Control,简称IoC)特性深受开发者喜爱。本文将深入探讨Spring的DI和IoC...

    spring依赖注入的实现原理

    在Spring框架中,依赖注入是核心特性之一,通过控制反转(Inversion of Control,IoC)实现了组件之间的解耦。 ### 依赖注入的基本概念 依赖注入允许开发者在不修改代码的情况下,通过配置来改变对象间的依赖关系。...

    Spring中使用Ioc控制反转

    ### Spring框架中的IoC控制反转详解 #### 一、IoC概述 控制反转(Inversion of Control,简称IoC)是一种设计思想,在Spring框架中,它主要用来解决对象依赖问题。传统的面向对象编程中,对象之间的依赖关系由对象...

    自定义spring控制反转(依赖注入)

    在Spring框架中,控制反转(IoC,Inversion of Control)和依赖注入(DI,Dependency Injection)是核心设计理念,它们极大地简化了Java应用的开发和维护。本文将深入探讨如何自定义Spring实现读取`...

Global site tag (gtag.js) - Google Analytics