Spring学习之IOC和DI

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangchengming1/article/details/81234326

首先我想明确它们之间的关系:

  • IOC:控制反转,把创建对象的过程交给Spring去管理,自己不做任何关注。
  • DI:依赖注入,向Bean里的属性进行设值。
  • DI是不可以自己独立进行工作的,必须要在IOC的基础上完成工作,也可以理解为DI是IOC的一种实现。

什么是IOC?

  • 首先我想谈一下我自己的想法

IOC全名是Inverse Of Control,意思是控制反转,那么这个控制反转到底是什么意思呢?通俗一点可以这样子理解:众所周知,在java程序中,完成每个业务逻辑必须至少需要两个或以上的对象来协助完成。在传统编程中,假设我的程序中存在两个对象A和B,当A需要B的一些帮助,我们必须去手动实例化这个对象(类似new object()这样子的语法),而IOC的思想是:我们可以把对象之间的引用关系交给Spring来管理,对象的创建、维护、销毁等生命周期的这些操作程序人员完全不用自己关注,全权交给Spring容器,其实这样就把控制权交给了Spring,所以就叫做控制反转。

  • Bean的生命周期

在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就说每一个Bean的别名只能维持一个实例,而不是每次都产生一个新的对象。
这里写图片描述

  • 注入的三种方式
    • 基于XML的bean定义(需要提供setter方法)

首先定义Student和Teacher类。

package com.demo.ioc.Bean;

public class Student {

	private String name;
	
	private Teacher teacher;

	public String getName() {
		return name;
	}

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

	public Teacher getTeacher() {
		return teacher;
	}

	public void setTeacher(Teacher teacher) {
		this.teacher = teacher;
	}
	
	
}

package com.demo.ioc.Bean;

public class Teacher {

	private String name;

	public String getName() {
		return name;
	}

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

bean1.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 
    <bean id="student" class="com.demo.ioc.Bean.Student">
        <property name="name" value="张三"/>
        <property name="teacher" ref="teacher"/>
    </bean>
 
    <bean id="teacher" class="com.demo.ioc.Bean.Teacher">
        <property name="name" value="李四"/>
    </bean>
</beans>

package com.demo.ioc.spring;

import org.springframework.context.support.FileSystemXmlApplicationContext;

import com.demo.ioc.Bean.Student;
import com.demo.ioc.Bean.Teacher;

public class Main {

	public static void main(String args[]) throws Exception{
        FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("src/main/resources/bean1.xml");
        Student student = (Student) context.getBean("student");
        Teacher teacher = (Teacher) context.getBean("teacher");
        System.out.println("学生的姓名:"+student.getName()+"。老师是"+student.getTeacher().getName());
        System.out.println("老师的姓名:"+teacher.getName());
    }

}

  • 基于注解的bean定义(不需要提供setter方法)
package com.demo.ioc.Bean;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("student")
public class Student {

	@Value("张三")
	private String name;
	
	@Resource
	private Teacher teacher;

	public String getName() {
		return name;
	}

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

	public Teacher getTeacher() {
		return teacher;
	}

//	public void setTeacher(Teacher teacher) {
//		this.teacher = teacher;
//	}
	
	
}

package com.demo.ioc.Bean;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("teacher")
public class Teacher {

    @Value("李四")
	private String name;

	public String getName() {
		return name;
	}

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

bean2.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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
 
    <!--扫描组件的包目录-->
    <context:component-scan base-package="com.demo.ioc.Bean"/>
 
</beans>
package com.demo.ioc.spring;

import org.springframework.context.support.FileSystemXmlApplicationContext;

import com.demo.ioc.Bean.Student;
import com.demo.ioc.Bean.Teacher;

public class Main {

	public static void main(String args[]) throws Exception{
        FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("src/main/resources/bean2.xml");
        Student student = (Student) context.getBean("student");
        Teacher teacher = (Teacher) context.getBean("teacher");
        System.out.println("学生的姓名:"+student.getName()+"。老师是"+student.getTeacher().getName());
        System.out.println("老师的姓名:"+teacher.getName());
    }

}

  • 基于JavaConfig定义(需要提供setter方法)
package com.demo.ioc.Bean;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeansConfiguration {
 
    @Bean
    public Student student(){
        Student student=new Student();
        student.setName("张三");
        student.setTeacher(teacher());
        return student;
    }
 
    @Bean
    public Teacher teacher(){
        Teacher teacher=new Teacher();
        teacher.setName("李四");
        return teacher;
    }
 
}

package com.demo.ioc.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.demo.ioc.Bean.BeansConfiguration;
import com.demo.ioc.Bean.Student;
import com.demo.ioc.Bean.Teacher;

public class Main {

	public static void main(String args[]) throws Exception{
		AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(BeansConfiguration.class);
//        FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("src/main/resources/bean2.xml");
        Student student = (Student) context.getBean("student");
        Teacher teacher = (Teacher) context.getBean("teacher");
        System.out.println("学生的姓名:"+student.getName()+"。老师是"+student.getTeacher().getName());
        System.out.println("老师的姓名:"+teacher.getName());
    }

}

  • 容器中Bean的作用域
    • 当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。Spring支持如下五种作用域:
  1. singleton: 单例模式,在整个Spring IoC容器中,singleton作用域的Bean将只生成一个实例。
  2. prototype: 每次通过容器的getBean()方法获取prototype作用域的Bean时,都将产生一个新的Bean实例。
  3. request:对于一次HTTP请求,request作用域的Bean将只生成一个实例,这意味着,在同一次HTTP请求内,程序每次请求该Bean,得到的总是同一个实例。只有在Web应用中使用Spring时,该作用域才真正有效。
  4. session:该作用域将 bean 的定义限制为 HTTP 会话。 只在web-aware Spring ApplicationContext的上下文中有效。
  5. global session: 每个全局的HTTP Session对应一个Bean实例。在典型的情况下,仅在使用portlet context的时候有效,同样只在Web应用中有效。
  • 如何实现IOC

    • Spring IOC的实现用到了设计模式:简单工厂模式+反射来实现IoC。
  • BeanFactory和ApplicationContext的区别
    ApplicationContext接口,它由BeanFactory接口派生而来,因而提供BeanFactory所有的功能。ApplicationContext以一种更向面向框架的方式工作以及对上下文进行分层和实现继承,最主要的就是BeanFactory延迟加载,当使用到getBean的时候才会抛异常,而ApplicationContext在刚开始启动加载的时候就会抛出异常,这样有利于检查所依赖属性是否注入;所以通常情况下我们选择使用ApplicationContext。

什么是DI?

  • 全称为Dependency Injection,意思自身对象中的内置对象是通过注入的方式进行创建。
  • 它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,Spring就是通过反射来实现注入的。
  • 其实我个人觉得IOC和DI是一个东西。
public static Object newInstance(String className) {   
        Class<?> cls = null;   
        Object obj = null;   
        try {   
            cls = Class.forName(className);   
            obj = cls.newInstance();   
        } catch (ClassNotFoundException e) {   
            throw new RuntimeException(e);   
        } catch (InstantiationException e) {   
            throw new RuntimeException(e);   
        } catch (IllegalAccessException e) {   
            throw new RuntimeException(e);   
        }   
        return obj;   
    }

为什么要使用IOC?

在IOC出现以前,组件之间的协调关系是由程序内部代码来控制的,或者说,以前我们使用New关键字来实现两组间之间的依赖关系的。这种方式就造成了组件之间的互相耦合。IoC(控制反转)就是来解决这个问题的,它将实现组件间的关系从程序内部提到外部容器来管理。也就是说,由容器在运行期将组件间的某种依赖关系动态的注入组件中。

猜你喜欢

转载自blog.csdn.net/wangchengming1/article/details/81234326
今日推荐