Spring IOC的个人理解及Spring对bean的装配

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

IOC是什么?

IOC的英文全称是Inversion of Control,即控制反转。IOC并不是什么技术,而是一种设计思想。

IOC有什么好处,或者说你怎么理解控制反转?

这是恐怕是面试官对于Spring框架的问题中最为常见的一个问题了。
历史遗留问题:在平时我们开发Java程序的时候,对于一个要使用的对象往往我们需要new一个出来,主动权在我们开发者的手里,对象的创建时机往往由我们开发者决定。对象A中用到了对象B,而对象B中又用到了对象C和对象D,这样各种各样的相互依赖,会使程序的耦合度高了起来。
现在IOC出现了:IOC的出现就是为了解耦,它有一个专门的容器去自己创建对象,也就是说创建对象的控制权被反转了,创建对象的时机和动作发起者从原来开发者到现在的一个第三方容器的手中。对象A、对象B、对象C、对象D他们之间的依赖关系由于容器的出现从相互依赖变成了都只依赖于容器,因为对象的实例化都是由容器去完成的,原先的对象只需要持有依赖对象的引用即可,通过这种方法去达到解耦的目的。
引用知乎大神的一句总结:
IOC的思想最核心的地方在于,资源不由使用资源的双方管理,而由不使用资源的第三方管理,这可以带来很多好处。
第一,资源集中管理,实现资源的可配置和易管理。
第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度。
摘抄于:Spring IoC有什么好处呢?
再次引用开涛大神博客中的一句话:
IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:”别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。
摘抄于:【第二章】 IoC 之 2.1 IoC基础 ——跟我学Spring3

IOC在Spring中的体现

IOC是Spring的核心,对于Spring来说,所有需要被管理起来的资源都要进行登记,你需要配置一下Spring的配置文件,告诉Spring容器,你是什么,你需要什么,Spring容器会在程序运行到适当的时候给你你所要的东西,同样的也会像这样把你交给别人。所有对象都在Spring容器的管理之下,这些对象我们叫它bean。默认情况下Spring中定义的bean是以单例模式创建的。有默认自然就会有别的情况这就涉及到了bean的作用域了,暂且不提。Spring在程序运行时给bean提供它所需要的其他bean,这一点是通过DI来实现的。DI的英文全称是Dependency Injection(依赖注入),是IOC的一种实现方式。创建应用对象之间协作关系的行为通常称为装配,这也是依赖注入的本质。那Spring是怎么做的咧?
答案是Java的反射机制。众所周知,Java可以通过反射将一个给出的完整类名(字符串方式)来动态地生成对象。假设某个配置文件里面写好了一个类的全类名,通过读取配置文件就能获取到这个类的全类名,在运行时动态生成这个类,在赋值到需要的地方。这就完成了依赖注入,这也就是Spring的做法。

Spring对bean的装配

Spring提供3种主要的装配机制:
1.在xml中进行显示配置
2.在Java中进行显示配置
3.隐式的bean发现机制和自动装配

基于XML的显示配置——Setter注入和构造方法注入

Setter注入

Setter注入,顾名思义,被注入的属性要有set方法。对象注入使用<property>的ref属性。
以我之前的博客中Spring整合shiro的配置为例。
在类ShiroDbRealm中有userService的引用,及set方法

public void setUserService(UserServiceImpl userService) {
    this.userService = userService;
}

在spring-shiro.xml配置文件中需要如下配置才能成功注入userService。

<!-- 配置进行授权和认证的 Realm -->
<bean id="myRealm" class="com.gray.base.shiro.ShiroDbRealm">
    <property name="userService" ref="userService" />
</bean>
<bean id="userService" class="com.gray.user.service.impl.UserServiceImpl" />

当然,<property>标签不止可以注入对象,也可以注入一些简单的值和集合类型,普通值使用<property>标签的value值,数据结构则需要额外加上集合类型,如:

   <property name="citys">  
       <list>  
           <value>北京</value>  
           <value>上海</value>  
           <value>深圳</value>
           <value>广州</value>  
       </list>  
   </property> 

构造方法注入

通过构造方法注入依赖,如SqlSessionTemplate在Spring的配置文件中是这样声明的:

    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
          <constructor-arg index="0" ref="sqlSessionFactory" />   
          <constructor-arg index="1" value="BATCH" />  
     </bean> 

让我们进入到SqlSessionTemplate中,配置文件所写的,在实际实例化SqlSessionTemplate时会调用两个参数的构造方法。

public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {
        this(sqlSessionFactory, executorType, new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true));
    }

而<constructor-arg>标签中的index属性,通过index属性可以告诉Spring容器传递的依赖参数的顺序。构造方法注入也和Setter注入一样,同样可以注入一些简单的值和集合类型。

基于注解的注入

@Autowired
例如:

    @Autowired
    private UserDao<User> dao;

@Autowired可以用在类的任何方法上。
@Resource
由Java提供,可用于Setter方法,但是无法用于构造方法上。
@Value
可直接用于获取被Spring管理的properties属性文件的值。

db.url=jdbc:mysql://127.0.0.1:3306/test

例在配置文件中配置了引入的属性文件

<!-- 引入属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties" />

使用的时候只需要这样写@Value("${jdbc.url}")
这三个注解,会帮我们把声明在Spring中bean自动装配到需要的地方。

好了,说了那么多,一切都是要我们在XML配置文件中设置了这些bean为前提我们才能用,应用程序里面有那么多类,难道我们要一一为它们都去配置文件里面声明吗?
答案是否定的,Spring为我们提供了包扫描机制
例如在配置文件中配置了要扫描的路径

<!-- 自动扫描(自动注入) -->
<context:component-scan base-package="要去扫描的路径" />

在启动的时候会根据配置文件中配置的要扫描的路径去扫描这些路径中包含@Component、@Service和@Repository等(Springmvc中加上@Controller)注解的类,并自动视为已经注册的bean,如果没有为bean配置名称,那Spring会给它们一个默认的名字,类名(第一个字符小写)变成bean名称。

总之,Spring框架强大的注入功能帮我们管理bean的生命周期,我们只需要关注怎么使用就好了,Spring具有非常大的灵活性,在实际开发中注解和xml配合使用可以大大增加代码的灵活性。
以上所说的只是Spring的注入和装配bean的一些基础知识,但这些东西会一直伴随着我们整个开发工作中,还是要多熟记。如果想知道Spring在初始化的时候到底还做了些什么,具体还得去研读一下源码,但在这里就不多加叙述了。

猜你喜欢

转载自blog.csdn.net/donggua3694857/article/details/68969555
今日推荐