Spring中IOC的简单实战理解

1 概述

IOC:控制反转
网上关于IOC有大量解释,但是大都趋于理论,或多或少有些难以理解,
最近我看了官方文档的解释以及一切大神的解说,根据自己的总结实现
了一个能说明Spring中IOC思想的简答例子,一来梳理知识,二来希望
能帮助到被IOC困惑的其他人。

首先,我们回顾下我们平时传统上不进行IOC时如果需要创建调用对象应该怎么实现,以下我们有4个类,分别是Dog,Animals,Cat,SayHello

public class interface Animals{
	public void sayHello();
}
public class Dog implements Animals{
	@Override
	public void sayHello(){
		System.out.println("wang wang");
	}
}
public class Cat implements Animals{
	@Override
	public void sayHello(){
		System.out.println("miao miao");
	}
}
public class SayHello{
	private Animals animals;
	public SayHello(){
		this.animals = new Dog();
	}
}

上面就是我们日常使用时调用Animals类的方法,通过SayHello类来实现Animals的创建。当我们创建SayHello类时,Animals类也同时被创建,当然Animals类是通过Dog类来创建的。这样做有一个缺陷,那就是我们的目的是创建SayHello的同时,Animals类可以同时被创建,上述方法我们只能认定其为Dog。这其中的关系是SayHello类控制着Animals类的对象创建,前人有了一种思考,我们能不能将这种创建交付给第三方而不是通过SayHello创建呢?这就是IOC的初衷。
因此,我们调整下SayHello

public class SayHello{
	private Animals animals;
	public SayHello(){
	}
	public void setAnimals(Animals animals){
		this.animals = animals;
	}
	public Animals getAnimals(){
		return this.animals;
	}
}

IOC容器创建SayHello对象,然后通过setter方法将Animals对象“注入”到SayHello中,IOC正对SayHello对象进行“依赖注入”,这里的依赖关系指的是对象之间的关系依赖(SayHello 与Animals)
在这里插入图片描述
IoC容器将作为管理器,同时创建SayHello和Animals对象,这就是IOC,上面是简要的概述,如果你还不是很清楚那我们接下来根据一个具体的项目来更深一步地理解它!

2 项目实现

2.1 创建项目

在这里插入图片描述
此为项目的工程目录结构

2.2 代码实现

首先我们建立一个通用接口 Animals.java

package com.caigentan.spring.ioc;  
public interface Animals {     
	public String getHello();     
	public String getBye(); 
}

接下来是分别对Animals接口的具体实现 Dog.java,Cat.java,Duck.java
Dog.java

package com.caigentan.spring.impl;  
import com.caigentan.spring.ioc.Animals;  
public class Dog implements Animals {     
	@Override     
	public String getHello() {         
		return "wang wang Hello";     
	}      
	
	@Override     
	public String getBye() {         
		return "wang wang Bye";    
	 }
}

Cat.java

package com.caigentan.spring.impl;  
import com.caigentan.spring.ioc.Animals;  

public class Cat implements Animals {     
	@Override     
	public String getHello() {
		return "miao miao Hello";     
	}      
	@Override     
	public String getBye() {         
		return "miao miao Bye";     
	} 
}

Duck.java

package com.caigentan.spring.impl;  
import com.caigentan.spring.ioc.Animals; 

public class Duck implements Animals {     
	@Override     
	public String getHello() {         
		return "ga ga Hello";     
	}      
	@Override     
	public String getBye() {         
		return "ga ga Bye";     
	}
}

构建Spring bean

HelloService.java

package com.caigentan.spring.bean;  
import com.caigentan.spring.ioc.Animals; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Service; 
import src.main.java.com.caigentan.spring.Language;  
// @Service注解,用于注解一个类,以通知Spring该类是一个Spring Bean 
@Service 
public class HelloService {     
	// @Autowired注解用于在一个字段上注释,以通知Spring我们向字段注入值     
	@Autowired     
	private Animals animals;      
	public HelloService(){      
	
	}      
	public void sayHello(){         
		String hello = animals.getHello();         
		System.out.println("Hello:" + hello);     
	} 
}

MyRepository.java

package com.caigentan.spring.bean;  
import org.springframework.stereotype.Repository;  
import java.util.Date;  
@Repository 
public class MyRepository {     
	public String getAppName(){         
		return "Hello caigentan";     
	}      
	
	public Date getSystemDate(){         
		return new Date();     
	} 
}

MyComponent.java

package com.caigentan.spring.bean;  
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Component;  
/**  
* 此类在此处我主要是用于解释@Component注解的作用,方便后面理解 bean 的概念  
*/ 
@Component 
public class MyComponent {     
	@Autowired     
	private MyRepository repository;      
	public void showAppInfo(){         
		System.out.println(repository.getAppName());         
		System.out.println("Now : " + repository.getSystemDate());     
	} 
}

2.3 测试结果

TestProgram.java

package com.caigentan.spring;  

import com.caigentan.spring.bean.HelloService; 
import com.caigentan.spring.bean.MyComponent; 
import com.caigentan.spring.bean.MyRepository; 
import com.caigentan.spring.config.AppConfiguration; i
mport com.caigentan.spring.ioc.Animals; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.annotation.AnnotationConfigApplicationContext;  

public class TestProgram {     
	public static void main(String[] args) {         
		ApplicationContext context = new AnnotationConfigApplicationContext(AppConfiguration.class);          				
		System.out.println("****************************");         
		Animals animals = (Animals)context.getBean("animals");         
		System.out.println("beans is " + animals);         
		System.out.println("animal beans Bye: " + animals.getBye());         
		System.out.println("****************************");         
		HelloService service = (HelloService) context.getBean("helloService");         
		service.sayHello();         
		System.out.println("****************************");         
		MyComponent component = (MyComponent)context.getBean("myComponent");         
		component.showAppInfo();         
		System.out.println("****************************");         
		MyRepository repository = (MyRepository)context.getBean("myRepository");         
		System.out.println(repository.getAppName());         
		System.out.println(repository.getSystemDate());     
	} 
}

先看结果,再分析:
在这里插入图片描述
解释:
在这里插入图片描述
那么,这个过程中IOC究竟干了什么呢?他们的这些注解又是如何工作的?别急,听我慢慢道来

首先我们应该了解,在运行过程中,我们已经将对象间的依赖交给了IOC,无需我们自己构造(各种注解实现)。在此时IOC中应该存在这些玩意儿:
在这里插入图片描述
是不是清楚了许多?从上我们可以知道关于IOC的以下几点:
Q1、IOC里存放什么?
A1、IoC容器中包含应用程序中使用的所有Spring bean的容器。

Q2、IOC具体指什么?
A2、如果一个对象是传统上从一个类创建的,那么它的字段将在类内部分配值。相反,对于Spring,它的对象和字段的值是由名为IOC的对象从外部注入的

到此,我想你应该对Spring 的IOC机制有了一个比较清晰的认识。另外对于博文中的一些对于初学者可能比较晦涩难懂的概念我在此也作一些解释

  1. Q:@Repository,@Component,@Service都是为了向IOC中注入Spring Bean那么这3中注解有什么区别呢,我应该改如何在合适的场景使用?
    A:根据我的一些实践,我可以说,这3种注解在功能实现上是没区别的,无论使用哪一个都可以使用预期的功能(不信你项目中这3类注解相互替换试试),但是应该根据自己的项目合理选择注解以方便使用(可以根据他们的字面意思来使用)。

  2. Q: @AutoWired与@Bean的区别与联系是什么?
    A:@AutoWired与@Bean做的是不同的事,
    @Bean 告诉Spring’这是此类的一个实例,请保留该类,并在我询问时将其还给我’。
    @Autowired说“请给我一个该类的实例,例如,我@Bean之前用注释创建的一个实例”。本项目中HelloService类中animals获得AppConfiguration类中的@Bean(name = “animals”),此@Bean()与getter方法获得一个new Dog(),都是一一对应的。
    在Spring中创建的类作为Bean时,自动将其首字母小写作为约束

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值