Spring基础--控制反转(IOC)、bean的生命周期及依赖注入(DI)

本文深入解析Spring框架中的控制反转(IoC)与依赖注入(DI)原理,包括核心容器的实现类、bean的管理细节、作用范围及生命周期,同时介绍了三种依赖注入方式和集合数据的注入。

控制反转IOC(Inversion of Control)

1、基础

概念: Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。从而减少各对象之间的互相依赖,降低耦合。
控制: 通过IOC容器控制对象创建。
反转: 传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象。
DI: 依赖注入,被注入对象依赖IoC容器配置依赖对象。
细节详解:
1、 ApplicationContext三个常用实现类:
a、ClassPathXmlApplicationContext—加载类路径下的配置文件,配置文件必须在类路径下
b、FileSystemXmlApplicationContext—加载磁盘任意路径下的配置文件(必须有访问权限)
c、AnnotationConfigApplicationContext—用于读取注解创建容器
2、核心容器两个接口引发出的问题:
a、ApplicationContext:(构造函数测试)----单例对象适用
构建核心容器时,创建对象采用立即加载的方式,读取完配置文件bean马上创建bean中所有对象
b、BeanFactory: ----多例对象适用
构建核心容器时,创建对象采用延迟加载的方式,根据bean id获取对象时,才创建对象

2、spring基于XML的IOC环境搭建示例

a、添加依赖

  <dependency>
  		<groupId>org.springframework</groupId>
  		<artifactId>spring-context</artifactId>
  		<version>5.0.6.RELEASE</version>
  	</dependency>

b、配置文件配置

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    
    
    <bean id="beanTest" class="com.my.ghost.admin.test.controller.BeanTest"></bean>
</beans>

c、代码实现

package com.my.ghost.admin.test.controller;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

public class Test {
	public static void main(String[] args) {
		/**
		 *使用 ClassPathXmlApplicationContext
		 */
		/*
		 * ApplicationContext resource = new ClassPathXmlApplicationContext("bean.xml");
		 * BeanTest beanTest = (BeanTest) resource.getBean("beanTest"); 
		 * beanTest.say();
		 */
		
		/**
		 * 使用 FileSystemXmlApplicationContext
		 */
		/*
		 * ApplicationContext resource = 
		 * new FileSystemXmlApplicationContext("E:\\sts-4.4.0.RELEASE\\workspace\\GHOSTKILLER\\GHOSTKILLER\\ghost_killer\\ghost_admin\\src\\main\\resources\\bean.xml"
		 * ); 
		 * BeanTest beanTest = (BeanTest) resource.getBean("beanTest");
		 * beanTest.say();
		 */
		
		/**
		 * 使用 AnnotationConfigApplicationContext--配合@Bean使用
		 */
		/*
		 * ApplicationContext resource = new
		 * AnnotationConfigApplicationContext(BeanTest.class); resource.getBean("say");
		 */
		
		/**
		 * 使用 BeanFactory
		 */
		Resource resource = new ClassPathResource("bean.xml");
		BeanFactory beanFactory = new XmlBeanFactory(resource);
		BeanTest beanTest = (BeanTest)beanFactory.getBean("beanTest");
		beanTest.say();
	}
}

@Component
class BeanTest{
	@Bean(name = "say")
	public void say() {
		System.out.println("注入获取!");
	}
}
 

3、spring对bean的管理细节

3.1、创建bean的三种方式
a、使用默认构造函数创建
在spring配置文件中使用bean标签配置id和class,如果对应类中没有默认构造函数则无法创建,需加入相应的construct-arg,也可用于对指定方法传参:如下

class BeanTest{
	BeanTest(String str){
		System.out.println("str");
	}
	public void say(){
		System.out.println("aaaa");
	}
}
 <bean id="beanTest" class="com.my.ghost.admin.test.controller.BeanTest">
    	<constructor-arg value="abc"></constructor-arg>
 </bean>

b、使用普通工厂中的方法创建并存入spring容器(工厂中的方法必须为静态):工厂本身不用创建对象,通过静态方法调用。
java代码

package com.my.ghost.admin.test.controller;

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

public class Test {
	public static void main(String[] args) {
		ApplicationContext app = new ClassPathXmlApplicationContext("bean.xml");
		BuyHouse buyHouse = (BuyHouse) app.getBean("beanFactory");
		buyHouse.buy();
	}
}

interface Behavior{
	public void buy();
}

class BuyHouse implements Behavior{
	@Override
	public void buy() {
		System.out.println("我要买房子!");
	}
}

class BuyFood implements Behavior{
	@Override
	public void buy() {
		System.out.println("我要买食物!");
	}
}

class BeanFactory {
	public static Behavior getObj(String objName) {
		switch (objName) {
		case "买房子":
			return new BuyHouse();
		case "买食物":
			return new BuyFood();
		default:
			return null;
		}
	}
}

配置文件

<bean id="beanFactory" class="com.my.ghost.admin.test.controller.BeanFactory" factory-method="getObj">
    <constructor-arg value="买房子"></constructor-arg>
</bean>

c、使用实例工厂创建bean(工厂不能使用静态):工厂本身需要创建对象,需要先new一个工厂实例。

public class Test {
	public static void main(String[] args) {
		ApplicationContext app = new ClassPathXmlApplicationContext("bean.xml");
		BuyHouse buyHouse = (BuyHouse) app.getBean("buyHouse");
		buyHouse.buy();
	}
}

//接口
interface Behavior{
	public void buy();
}

//对象A
class BuyHouse implements Behavior{
	@Override
	public void buy() {
		System.out.println("我要买房子!");
	}
}

//对象B
class BuyFood implements Behavior{
	@Override
	public void buy() {
		System.out.println("我要买食物!");
	}
}

//工厂类
class BeanFactory {
	public Behavior getObj(String objName) {
		switch (objName) {
		case "买房子":
			return new BuyHouse();
		case "买食物":
			return new BuyFood();
		default:
			return null;
		}
	}
}

3.2、bean对象的作用范围
bean标签中的scope属性
取值:
singleton—默认值,单例
prototype—多例
request—作用于web应用的请求范围
session—作用于web应用的会话范围
global-session—(多个ip范围内的session)作用于集群环境会话范围,当不是集群环境时,相当于session
3.3、bean对象的生命周期
1、单例对象—bean中配置
出生:当容器创建时对象出生 ----bean中 init-method属性指定初始化时触发的方法
活着:只要容器还在,对象一直活着
死亡:容器销毁,对象死亡—bean中 destory-method属性指定销毁时触发的方法,使用销毁方法需要手动关闭容器 applicationContext.close()
2、多例对象
出生:使用对象时spring框架创建对象,init-method同上
活着:对象只要在使用过程中,一直活着
死亡:当对象长时间不用且没有别的对象引用时,用java的垃圾回收器回收

4、Spring的依赖注入(Dependency Injection)

4.1、三种可注入的数据
a、基本类型和String
b、其他bean类型
c、复杂类型/集合类型
4.2、三种注入方式
a、使用构造函数提供
java代码

public class Test {
	public static void main(String[] args) {
		ApplicationContext app = new ClassPathXmlApplicationContext("bean.xml");
		B b = (B) app.getBean("b");
		b.useA();
	}
}

class A {
	public void say() {
		System.out.println("aaaaaaaa");
	}
}

class B {
	private A a;
	
	B(A a){
		this.a = a;
	}
	
	public void useA() {
		a.say();
	}
}
<bean id="a" class="com.my.ghost.admin.test.controller.A"></bean>
<bean id="b" class="com.my.ghost.admin.test.controller.B">
    	<constructor-arg name="a" ref="a"></constructor-arg>
</bean>

b、使用set方法提供
java代码

public class Test {
	public static void main(String[] args) {
		ApplicationContext app = new ClassPathXmlApplicationContext("bean.xml");
		B b = (B) app.getBean("b");
		b.useA();
	}
}

class A {
	public void say() {
		System.out.println("aaaaaaaa");
	}
}

class B {
	private A a;
	
	//实现set/get方法
	public void setA(A a) {
		this.a = a;
	}
	public A getA() {
		return this.a;
	}
	
	public void useA() {
		a.say();
	}
}

配置文件

<bean id="a" class="com.my.ghost.admin.test.controller.A"></bean>
<bean id="b" class="com.my.ghost.admin.test.controller.B">
    	<property name="a" ref="a"></property>
</bean>

c、使用注解提供
4.3、注入集合数据----不用考虑对象集合,因为对象集合本身就可以当成一个bean
list同set和Array相同

private List<String> list;

<bean id="xxx" class="xxx">
    <list>
        <value>1</value>
        <value>2</value>
    </list>
</bean>

Map

private Map<key,value> map;

<bean id="xxx" class="xxx">
    <map>
        <entry key="xx" value="xx"/>
    </map>
</bean>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值