IT小栈

  • 主页
  • Java基础
  • RocketMQ
  • Kafka
  • Redis
  • Shiro
  • Spring
  • Spring Boot
  • Spring Cloud
  • 资料链接
  • 关于
所有文章 友链

IT小栈

  • 主页
  • Java基础
  • RocketMQ
  • Kafka
  • Redis
  • Shiro
  • Spring
  • Spring Boot
  • Spring Cloud
  • 资料链接
  • 关于

Spring IOC和DI

2019-06-23

很多人认为IOC就是DI他们之间是对等的,其实不然。

很多文章中都提到他们的分别依赖:
谁依赖于谁?为什么需要依赖?

注入:谁注入于谁?到底注入什么?
控制反转:谁控制谁?控制什么?
这种描述很难让别人理解,感觉有点教科书的意味。下面我就简单的说下我的看法:

一、IOC和DI区别

IOC( inversion of control)控制反转,控制反转是一种思想,结合程序通俗的讲,创建对象的方式反转了。

以前对象的创建是由我们开发人员自己维护创建,包括依赖关系都是自己进行注入(创建依赖对象new),例如:我们经常提到的三层框架Web层、Service层、Dao层。web层依赖于service层,service依赖于dao层,以前我们管理service层调用dao层的数据时,都会new一个对象调用其中的方法。

使用spring后对象的创建及依赖的对象都由spring完成创建和注入,控制反转就是对象的创建方式,从我们自己创建到交个spring(程序)进行创建管理

DI(Dependency Injection)依赖注入,依赖注入是一种技术,它是对控制反转这种思想进行技术支撑。依赖注入即控制反转中举的例子。

二、Spring创建Bean对象的三种方式

首先我们看看不用spring时如何创建对象

1
2
3
4
5
6
7
public class UserServiceImpl {
public List<User> getUserList(){
//servi层调用dao层的方法,需要手动创建dao对象
UserDao userDao = new UserDao();
return userDao.getUserList();
}
}

使用spring,spring就会自动创建对象(前提按照一定的规则,这个规则是spring规定的)

第一种方式构造器注入创建(默认的创建方式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class User {
public User() {
System.out.println("User对象构造器注入创建!!!!");
}
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
}

Spring配置文件applicationContext.xml中配置

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:p="http://www.springframework.org/schema/p"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">

    <!-- set方式注入: -->
    <bean  name="user" class="cn.mingxungu.bean.User" />
</beans>

测试代码

1
2
3
4
5
6
7
8
9
@Test
public void fun1(){
//1 创建容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("cn/mingxungu/c_injection/applicationContext.xml");
//2 向容器"要"user对象
User u = (User) ac.getBean("user");
//3 打印user对象
System.out.println(u);
}

结果:

User对象构造器注入创建!!!! User [name=null, age=null]

第二种方式静态工厂创建(了解)

1
2
3
4
5
6
public class UserFactory {
public static User createUser(){
System.out.println("静态工厂创建User");
return new User();
}
}

Spring配置文件applicationContext.xml中配置

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">

<!-- 创建方式2:静态工厂创建
调用UserFactory的createUser方法创建名为user2的对象.放入容器
-->
<bean name="user2"
class="cn.mingxungu.b_create.UserFactory"
factory-method="createUser" ></bean>

</beans>

测试代码

1
2
3
4
5
6
7
8
9
10
//创建方式2:静态工厂
@Test
public void fun2(){
//1 创建容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("cn/mingxungu/b_create/applicationContext.xml");
//2 向容器"要"user对象
User u = (User) ac.getBean("user2");
//3 打印user对象
System.out.println(u);
}

输出结果

静态工厂创建User
User [name=null, age=null]

注意:静态工厂方法在配置文件中制定了工厂方法名称factory-method=”createUser”

第三种方式实例工厂创建(了解)

1
2
3
4
5
6
public class UserFactory {
public User createUser2(){
System.out.println("实例工厂创建User");
return new User();
}
}

Spring配置文件applicationContext.xml中配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">

<!-- 创建方式3:实例工厂创建
调用UserFactory对象的createUser2方法创建名为user3的对象.放入容器
-->
<bean name="user3"
factory-bean="userFactory"
factory-method="createUser2" ></bean>
<bean  name="userFactory"
        class="cn.mingxungu.b_create.UserFactory"   ></bean>
</beans>

测试代码

1
2
3
4
5
6
7
8
9
10
//创建方式3:实例工厂
@Test
public void fun3(){
//1 创建容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("cn/mingxungu/b_create/applicationContext.xml");
//2 向容器"要"user对象
User u = (User) ac.getBean("user3");
//3 打印user对象
System.out.println(u);
}

输出结果

实例工厂创建User
User [name=null, age=null]

总结:

一、元素指定了factory-method属性,Spring就不再调用构造器来创建Bean实例,而是调用工厂方法来创建Bean实例。如果同时指定了class和factory-method两个属性,Spring就会调用静态工厂方法来创建Bean。Spring将先解析配置文件,并根据配置文件指定的信息,通过反射调用静态工厂类的静态工厂方法,将该静态工厂方法的返回值作为Bean实例。在这个过程中,Spring不再负责创建Bean实例,Bean实例是由用户提供的静态工厂类负责创建的。

二、实例工厂方法与静态工厂方法只有一点不同:调用静态工厂方法只需要使用工厂类即可,而调用实例工厂方法则需要工厂实例。所以在配置时,静态工厂方法使用class指定静态工厂类,实例工厂方法使用factory-bean指定工厂实例。
采用实例工厂方法创建Bean的元素时需要指定两个属性:
factory-bean:工厂bean的id
factory-method:实例工厂的工厂方法

三、Bean 生命周期



详解:

Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

1、Bean自身的方法:这个包括了Bean本身调用的方法和通过配置文件中的init-method和destroy-method指定的方法

2、Bean级生命周期接口方法:这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法

3、容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。

4、工厂后处理器接口方法:这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器  接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

说明:

在配置文件aplicationContext.xml中配置的bean的生命周期

1
<bean  name="user" class="cn.mingxungu.bean.User"  init-method="init" destroy-method="destory" />

init-method=”init”:配置一个方法作为生命周期初始化方法,在该Bean中编写一个init方法。spring会在对象创建之后立即调用.

destroy-method=”destory”:配置一个方法作为生命周期的销毁方法,在该Bean中编写一个destory方法。spring容器在关闭并销毁所有容器中该对象之前调用.

详细的测试参考:http://www.cnblogs.com/zrtqsk/p/3735273.html

四、Bean属性的注入

注入方式:set方法注入、构造函数注入、p名称空间注入、spel注入

set方法注入:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- set方式注入: -->
<bean name="user" class="cn.mingxungu.bean.User" >
<!--值类型注入: 为User对象中名为name的属性注入tom作为值 -->
<property name="name" value="tom" ></property>
<property name="age" value="18" ></property>
<!-- 引用类型注入: 为car属性注入下方配置的car对象 -->
<property name="car" ref="car" ></property>
</bean>
<!-- 将car对象配置到容器中 -->
<bean name="car" class="cn.mingxungu.bean.Car" >
    <property name="name" value="兰博基尼" ></property>
    <property name="color" value="黄色" ></property>
</bean>

构造函数注入(掌握)

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 构造函数注入 -->
<bean name="user2" class="cn.mingxungu.bean.User" >
<!-- name属性: 构造函数的参数名 -->
<!-- index属性: 构造函数的参数索引 -->
<!-- type属性: 构造函数的参数类型-->
<constructor-arg name="name" index="0" type="java.lang.Integer" value="999" ></constructor-arg>
<constructor-arg name="car" ref="car" index="1" ></constructor-arg>
</bean>
<!-- 将car对象配置到容器中 -->
<bean name="car" class="cn.mingxungu.bean.Car" >
    <property name="name" value="兰博基尼" ></property>
    <property name="color" value="黄色" ></property>
</bean>

p名称空间注入

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 
spel注入: spring Expression Language sping表达式语言
-->
<bean name="user4" class="cn.mingxungu.bean.User" >
<property name="name" value="#{user.name}" ></property>
<property name="age" value="#{user3.age}" ></property>
<property name="car" ref="car" ></property>
</bean>
<!-- 将car对象配置到容器中 -->
<bean name="car" class="cn.itcast.bean.Car" >
<property name="name" value="兰博基尼" ></property>
<property name="color" value="黄色" ></property>
</bean>

spel注入

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 
spel注入: spring Expression Language sping表达式语言
-->
<bean name="user4" class="cn.mingxungu.bean.User" >
<property name="name" value="#{user.name}" ></property>
<property name="age" value="#{user3.age}" ></property>
<property name="car" ref="car" ></property>
</bean>
<!-- 将car对象配置到容器中 -->
<bean name="car" class="cn.itcast.bean.Car" >
<property name="name" value="兰博基尼" ></property>
<property name="color" value="黄色" ></property>
</bean>
本文作者: 顾 明 训
本文链接: https://www.itzones.cn/2019/06/23/Spring-IOC和DI/
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!
  • IOC和DI
  • Spring创建Bean
  • Bean生命周期
  • Sping属性注入
  • spring

扫一扫,分享到微信

微信分享二维码
RocketMQ简单介绍
SpringMVC异常统一处理
  1. 1. 一、IOC和DI区别
  2. 2. 二、Spring创建Bean对象的三种方式
    1. 2.1. 第一种方式构造器注入创建(默认的创建方式)
    2. 2.2. 第二种方式静态工厂创建(了解)
    3. 2.3. 第三种方式实例工厂创建(了解)
  3. 3. 三、Bean 生命周期
  4. 4. 四、Bean属性的注入
    1. 4.1. set方法注入:
    2. 4.2. 构造函数注入(掌握)
    3. 4.3. p名称空间注入
    4. 4.4. spel注入
© 2020 IT小栈
载入天数...载入时分秒... || 本站总访问量次 || 本站访客数人次
Hexo Theme Yilia by Litten
  • 所有文章
  • 友链

tag:

  • jvm
  • Java基础
  • kafka HW
  • kafka Leader Epoch
  • kafka
  • kafka位移主题
  • kafka位移提交
  • kafka副本机制
  • kafka ISR
  • zookeeper
  • kafka消息丢失
  • kafka日志存储
  • kafka Log Clean
  • kafka Log Compaction
  • kafka消费位移设置
  • kafka Rebalance
  • kafka分区算法
  • kafka生产者拦截器
  • kafka SASL/SCRAM
  • kafka ACL
  • redis
  • redis Ziplist
  • redis Hashtable
  • redis LinkedList
  • redis QuickList
  • redis intset
  • redis String
  • redis SDS
  • redis SkipList
  • redisDb
  • redisServer
  • redis 简介
  • Redis Cluster
  • 主从同步
  • RocketMQ高可用HA
  • 事务消息
  • 内存映射
  • MMAP
  • 同步刷盘
  • 异步刷盘
  • 消息存储文件
  • RocketMQ安装
  • 延迟消息
  • RocketMQ入门
  • 推拉模式
  • PushConsumer
  • 消费结果处理
  • rebalance
  • RocketMQ权限控制
  • RocketMQ ACL
  • 消息过滤
  • 消息重试
  • 消费位置
  • 集群消费
  • 广播消费
  • 运维命令
  • shiro源码分析
  • shiro入门
  • IOC和DI
  • Spring创建Bean
  • Bean生命周期
  • Sping属性注入
  • 异常
  • SpringMVC
  • springCloud
  • Eureka

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

  • 我的OSCHINA
  • 我的CSDN
  • 我的GITHUB
  • 一生太水