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

被折叠的 条评论
为什么被折叠?



