通过上篇文章大概知道ioc、DI的概念了,下面我们详细介绍一下

一、Spring IOC创建对象

IOC通过上文的介绍作用是控制创建对象的解释权,我们把代码重新看一下

//User.java
public class User {
private String username;
private String password; /**
* 省略有参无参构造器,getter/setter方法
*/
}

我们也不创建dao、service类了,直接就用这个User类来测试

配置文件:applicationContext.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">
<!-- id:创建的bean的唯一标识,作用是区分其它的bean
class:创建的对象的全限定名(包名+类名) -->
<bean id="user" class="com.ty.bean.User"></bean> </beans>
  1. bean的id获取IOC容器中的对象
//测试文件
public class MyTest {
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
@Test
public void test1(){
User user = (User) context.getBean("user");
System.out.println(user);
}
}

这是IOC创建对象的第一种方式即通过bean的id获取IOC容器中的对象:context.bean("配置文件bean中的id")

还有另外两种方式 :

  1. 通过bean的类型获取对象:context.bean(注入对象的class类型)
 @Test
public void test2(){
User user = context.getBean(User.class);
System.out.println(user);
}

这种注入方法有劣势,即:配置文件中有多个同类型的bean(即class重复)时,注入对象就会报错,例如:

<?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">
<!-- id:创建的bean的唯一标识,作用是区分其它的bean
class:创建的对象的全限定名(包名+类名) -->
<bean id="user" class="com.ty.bean.User"></bean>
<bean id="use2" class="com.ty.bean.User"></bean> </beans>

再接着运行测试文件的时候就会报NoUniqueBeanDefinitionException异常

  1. 通过bean的id和类型获取对象:context.bean("配置文件bean中的id",注入对象的class类型)
 @Test
public void test3(){
User user = context.getBean("user",User.class);
System.out.println(user);
}

二、SpringDI注入

光创建对象没用,最重要的还是为对象赋值,我们说过DI是IOC的实现,DI更能通过代码体现出来,接下开我们依次介绍几种赋值方式

1、属性注入(即setter注入)

1)简单类型(基本类型+String类型)
 <bean id="user" class="com.ty.bean.User">
<!-- property:表示属性注入
name:属性的名字,其实是常规bean中set之后的名字(首字母小写)
value:属性值 -->
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
2)复杂类型(引用类型)
public class Address {
private String city; /**
* 省略有参无参构造器,getter/setter方法
*/
} public class User {
private String username;
private String password;
private String[] hobby;
private Address address;
private List list;
private Set set;
private Map map;
private Properties properties; /**
* 省略有参无参构造器,getter/setter/toString方法
*/
}
<!-- private String[] hobby   -->
<property name="hobby">
<array>
<value>吃饭</value>
<value>看电影</value>
<value>打游戏</value>
<!-- 表示赋空值,可以起占位作用-->
<null></null>
</array>
</property>
<!--private Address address- 可以有2种注入方式,一种方式在property标签嵌套一个bean-->
<!-- <property name="address">-->
<!-- <bean class="com.ty.bean.Address">-->
<!-- <property name="city" value="大连"></property>-->
<!-- </bean>-->
<!-- </property>--> <!--ref:引用的bean的id-->
<property name="address" ref="address"></property>
<!-- private List list-->
<property name="list">
<list>
<value>a</value>
<value>b</value>
<value>c</value>
</list>
</property>
<!-- private Set set-->
<property name="set">
<set>
<value>redio</value>
<value>book</value>
<value>game</value>
</set>
</property>
<!-- private Map map-->
<property name="map">
<map>
<entry key="1" value="北京"></entry>
<entry key="2" value="上海"></entry>
<entry key="3" value-ref="address"></entry>
</map>
</property>
<!-- private Properties properties-->
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">root</prop>
</props>
</property>
</bean> <bean id="address" class="com.ty.bean.Address">
<property name="city" value="大连"></property>
</bean>

List,Set,Map,Properties中还有一种注入方式,即util命名方式,主要的作用:方便别人引用

util命名空间方式
 <!--   private List list-->
<property name="list" ref="mylist"></property>
<!-- private Set set-->
<property name="set" ref="myset"></property>
<!-- private Map map-->
<property name="map" ref="mymap"></property>
<!-- private Properties properties-->
<property name="properties" ref="myproperties"></property>
</bean> <util:list id="mylist">
<list>
<value>a</value>
<value>b</value>
<value>c</value>
</list>
</util:list> <util:set id="myset">
<set>
<value>redio</value>
<value>book</value>
<value>game</value>
</set>
</util:set> <util:map id="mymap">
<entry key="1" value="北京"></entry>
<entry key="2" value="上海"></entry>
<entry key="3" value-ref="address"></entry>
</util:map> <util:properties id="myproperties">
<prop key="username">root</prop>
<prop key="password">root</prop>
</util:properties>
3)P 命名空间方式

除了上方util命名空间方式之外搭配着还有一个P命名空间

<bean id="user2" class="com.ty.bean.User" p:username="root" p:password="123456" p:address-ref="address" p:list-ref="mylist"></bean>
4)自动注入

可以按照一定规则进行装配注入,不用具体指定为某个属性赋值,在工厂中查找一个bean,为属性注入属性值。

<bean id="address" class="com.ty.bean.Address">
<property name="city" value="上海"></property>
</bean> <bean id="person" class="com.ty.bean.Person" autowire="byName"></bean>
  1. byName:按照bean的id进行装配

  2. byType:按照bean的类型来进行注入,但是如果有多个相同类型,就会报错,不知道选择哪一个具体的类型

2、构造器注入

public class User {
private String username;
private String password; /**
* 省略有参无参构造器,getter/setter方法
*/
}
 <bean id="user3" class="com.ty.bean.User">
<!--构造注入的constructor-arg标签里还有几个属性
name:形参列表的名称
value:实参的值
type:参数类型
index:参数索引,从0开始
-->
<constructor-arg name="username" value="root"></constructor-arg>
<constructor-arg name="password" value="123456"></constructor-arg>
</bean>

属性注入有P命名空间,构造器注入有C命名空间

1)C 命名空间
<bean id="user4" class="com.ty.bean.User" c:username="root" c:password="123456"></bean>
2)自动注入
<bean id="person" class="com.ty.bean.Person" autowire="constructor"></bean>
  1. constructor:使用构造器注入,形参列表必须要有对应 bean 对象

三、bean对象之间的关系

1、继承关系

 <bean id="parent" class="com.ty.bean.User">
<property name="username" value="root"></property>
</bean>
<!--parent:指定继承的bean信息-->
<bean id="son" class="com.ty.bean.User" parent="parent"></bean>

2、抽象关系

这个是在继承关系的父bean里添加abstract属性,这个作用就是该bean是否能实例化

 <bean id="parent" class="com.ty.bean.User" abstract="true">
<property name="username" value="root"></property>
</bean>

3、依赖关系

这个就是bean的先后创建顺序,depends-on依赖哪个bean就谁先创建谁,然后再创建本对象

<bean id="user5" class="com.ty.bean.User" depends-on="address"></bean>

<bean id="address" class="com.ty.bean.Address">
<property name="city" value="大连"></property>
</bean>

四、bean对象的作用域

通过scope属性指定当前bean的作用域,有四个值

singleton:单例模式,从IOC容器中获取的都是同一个对象,默认的作用域

prototype:多例模式,从IOC容器中获取的对象每次都是新创建

request:每次发送请求都会有一个新的对象

session:每一次会话都会有一个新的对象

<bean id="user5" class="com.ty.bean.User" scope="singleton"></bean>

ps:singleton作用域:每次在创建IOC容器完成之前此对象已经创建完成,即:

ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");

​ prototype作用域:每次是在需要用到此对象的时候才会创建,即

User user = (User) context.getBean("user");

五、工厂对象

静态工厂

工厂本身不需要创建对象,但是可以通过静态方法调用,对象=工厂类.静态工厂方法名();

public class PersonStaticFactory {
public static Person getInstance(String name){
Person person=new Person();
person.setId(1001);
person.setAge(18);
person.setName(name);
return person;
}
}
<!--静态工厂:类名.静态方法()-->
<bean id="person" class="com.ty.factory.PersonStaticFactory" factory-method="getInstance">
<constructor-arg value="jack"></constructor-arg>
</bean>
实例工厂

工厂本身需要创建对象,工厂类 工厂对象=new 工厂类;工厂对象.get对象名();

public class PersonInstanceFactory {
public Person getInstance(String name){
Person person=new Person();
person.setId(1001);
person.setAge(18);
person.setName(name);
return person;
}
}
<!--实例工厂:先创建工厂实例,然后调用工厂实例的方法
factory-bean:表示具体工厂类的实例
factory-method:表示具体工厂实例的方法
-->
<bean id="factory" class="com.ty.factory.PersonInstanceFactory"></bean>
<bean id="person" class="com.ty.bean.Person" factory-bean="factory" factory-method="getInstance">
<constructor-arg value="jack"></constructor-arg>
</bean>
继承FactoryBean

FactoryBean是Spring规定的一个接口,当前接口的实现类,Spring都会将其作为一个工厂,但是在ioc容器启动的时候不会创建实例,只有在使用的时候才会创建对象

public class MyFactoryBean implements FactoryBean {
/**
* 此方式是spring创建bean方式的一种补充,用户可以按照需求创建对象, 创建的对象交由spring IOC容器来进行管理,无论是否是单例,都是在用到的时候才会创建该对象,不用该对象不会创建
*/
@Override
public Person getObject() throws Exception { //创建的对象
Person person=new Person();
person.setId(1001);
person.setName("jack");
person.setAge(20);
return person;
} @Override
public Class<?> getObjectType() { //返回对象的类型
return Person.class;
} @Override
public boolean isSingleton() { //是否单例
return true;
}
}
<bean id="factoryBean" class="com.ty.factory.MyFactoryBean"></bean>

六、bean对象的对象的生命周期

创建
  • scope="singleton"(不配置lazy-init="true"属性),每次在创建IOC容器完成之前此对象已经创建完成
  • scope="prototype",每次是在需要用到此对象的时候创建(scope="singleton"配置lazy-init="true"属性也是这样)
初始化

在对象创建完成之后会调用初始化方法

  1. 实现InitializingBean接口

    //实现这个方法,完成初始化操作
    @Override
    public void afterPropertiesSet() throws Exception {
    System.out.println("afterPropertiesSet");
    }
  2. 对象中提供一个普通的方法同时配置Spring配置文件:

    public void init(){
    System.out.println("init");
    }
    <bean id="p" class="com.ty.bean.Person" init-method="init"></bean>

    顺序:对象的注入-》InitializingBean-》普通init-method

销毁
  1. 实现DisposableBean接口
 @Override
public void destroy() throws Exception {
System.out.println("destory");
}
  1. 定义一个普通的销毁方法同时配置Spring配置文件
 public void mydestory(){
System.out.println("mydestory");
}
<bean id="p" class="com.ty.bean.Person" scope="prototype" init-method="init" destroy-method="mydestory">
<property name="id" value="1001"></property>
</bean>

销毁方法只会在scope="singleton"时才会调用,而且需要对象关闭,例如:context.close()

七、配置bean对象初始化方法的前后处理方法

spring中包含一个BeanPostProcessor的接口,可以在bean的初始化方法的前后调用该方法,如果配置了初始化方法的前置和后置处理器,无论是否包含初始化方法,都会进行调用

public class MyBeanPostProcessor implements BeanPostProcessor {
//对象初始化之前执行
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization"+beanName);
return bean;
}
//对象初始化对象之后运行
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization"+beanName);
return bean;
}
}
 <bean class="com.ty.bean.MyBeanPostProcessor"></bean>
<bean id="p" class="com.ty.bean.Person" scope="prototype" init-method="init" destroy-method="mydestory">
<property name="id" value="1001"></property>
</bean>

八、配置文件参数化

就是把Spring配置文件中需要经常修改的字符串信息,转移到一个更小的配置文件中,方便后期的维护

例如:数据库连接

<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
</bean>
jdbc.username=root
jdbc.password=root
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/demo
//测试
@Test
public void test11() throws SQLException {
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
DruidDataSource dataSource = context.getBean("dataSource", DruidDataSource.class);
System.out.println(dataSource);
System.out.println(dataSource.getConnection());
}

Spring-IOC基本使用的更多相关文章

  1. 【初探Spring】------Spring IOC(三):初始化过程---Resource定位

    我们知道Spring的IoC起到了一个容器的作用,其中装得都是各种各样的Bean.同时在我们刚刚开始学习Spring的时候都是通过xml文件来定义Bean,Spring会某种方式加载这些xml文件,然 ...

  2. 【初探Spring】------Spring IOC(一)

    IOC:Inversion of Control(控制反转).IOC它所体现的并不是一种技术,而是一种思想,一种将设计好的对象交给容器来管理的思想.IOC的核心思想就体现在控制.反转这两个词上面,要理 ...

  3. spring ioc

    spring ioc是spring的核心之一,也是spring体系的基础,那么spring ioc所依赖的底层技术是什么的?反射,以前我们开发程序的时候对象之间的相互调用需要用new来实现,现在所有的 ...

  4. Spring IoC源码解析——Bean的创建和初始化

    Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...

  5. spring笔记6 spring IOC的中级知识

    1,spring ioc的整体流程,xml配置 spring ioc初始化的流程结合上图 步骤编号 完成的工作 1 spring容器读取配置文件,解析称注册表 2 根据注册表,找到相应的bean实现类 ...

  6. 谈谈对Spring IOC的理解(转)

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...

  7. 自己动手编写spring IOC源码

    前言:对于spring IOC概念不是很了解的朋友可以阅读我上一篇博客--轻松理解spring IOC(这两篇博客也是由于我的个人原因导致现在才发布,惭愧啊).通过这篇博客的理解之后,相信大家会对sp ...

  8. spring ioc 源码解析

    什么是ioc? 通俗的解释是:(spring)框架中,完成对象的创建和注入的容器. springIOC体系结构: spring IOC的创建是典型的工厂模式,这一系列的bean工厂如上所示. 其核心是 ...

  9. Spring:源码解读Spring IOC原理

    Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. I ...

  10. 谈谈对Spring IOC的理解

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...

随机推荐

  1. Java基础教程——Jshell

    Jshell 从java9开始,java提供Jshell工具,可以输入代码片段并马上看到运行结果. 对于简单的Java语句测试,不需要新建文件,编译,运行了 Microsoft Windows [版本 ...

  2. 2020.11.26 IntellJ idea激活码失效解决方法(最新idea激活码及安装参数!)

    今天是2020年11月26号,小伙伴们是不是有发现自己的idea激活码失效了,不瞒大家,小编也是一个JAVA开发者,到了公司打开idea,然后就发现事情不妙,经过1个多小时的摸索,终于把最近的安装参数 ...

  3. [TroubleShootting]Zabbix数据采集出现断点的问题

    背景 最近发现公司的Zabbix监控大屏上的监控图经常出现数据断点的现象,主要集中在一些自定义的监控项数据上,如下图: 原因 查看Zabbix Server日志以及zabbix官方手册后,分析可能原因 ...

  4. HTML的基本术语

    一.HTML含义1.根据W3C定义,HTML全称Hyper Text Markup Language: 超文本标记语言,用于定义文档的内容结构,该语言书写的代码通常会被浏览器解析执行.二.css含义1 ...

  5. 华为模拟器ensp老是弹出一堆英文up down,关闭

    英文内容: Mar 25 2015 20:38:21-08:00 Huawei DS/4/DATASYNC_CFGCHANGE:OID 1.3.6.1.4.1.2011.5.25.191.3.1 co ...

  6. java44

    1.使用封装工具类思想:三种输入模式下的工具类. dateUtils类, StringUtils类(判断字符串值是否为空), 调用工具类: String res = dateUtils.datetoS ...

  7. PyQt(Python+Qt)学习随笔:Mode/View中的枚举类 QItemSelectionModel.SelectionFlag取值及含义

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 以上取值可以通过或操作进行组合使用. 老猿Python,跟老猿学Python! 老猿Python博文 ...

  8. 使用k8s部署springboot+redis简单应用

    准备 本文将使用k8s部署一个springboot+redis应用,由于是示例,所以功能比较简单,只有设置值和获取值两个api. (1)设置值 (2)获取值 构建Web应用 (1)创建一个spring ...

  9. Jmeter(10)逻辑控制器

    逻辑控制器可以控制采样器的执行顺序,所以控制器需要和采样器一起使用 Jmeter中的逻辑控制器分为两类 1.控制测试计划执行过程中节点的逻辑顺序,如循环控制器.If控制器 2.对测试计划中的脚本进行分 ...

  10. 20201126-1 txt文件筛选与读写【】

    Exercise 1import os # 设置文件夹路径为'工作文件夹',获取文件夹下的所有文件和文件夹名称 path = './工作文件夹/' files_list = os.listdir(pa ...