根据时间安排,今天主要是对spring中IOC的理解。对于IOC的理解可以从以下几个角度去分析。

什么是IOC?如何使用案例来理解?

  • IOC有哪几种实现方式?
  • IOC的底层实现过程是什么?
  • 根据这几个角度] } C M,开始今天的故事,

1 什么是IOC?

对于IOC的理解,主要是停留在概念和几种注入的方式上,虽然知道其生命周期,但是对整个bean管理的宏观角度,理解的不够深刻。

IOC:G D s y P Z**# b n J = c 1 3控制反转(Inversion of CG ~ q c | A nontrol)容器,**是一种设计思想。意味着将你设计好的对象交给容器控制。

1.1 什么是依赖注入

这个概念的理解,我准C o ^ R K ;备使用一个案例来表示。如果a类中包含了b类,就说明a类对b类: { X产生了依赖。如一个人需要车,这就说人对车产生了依赖。

  1. classUser{
  2. Carcar;
  3. publicUser(){
  4. car=newCar();
  5. }
  6. }

上面这个案例,可以看到,在User类中,包含了Car类,也就说User类对Car类产生了依赖。

按照传统的方式,User类如( c 3 W l ( I H s果想要使用Car基本上就是在内部ne` m a ^ ; d / fw一个新对象即可。但是这样做缺点很大,new的方式也就意味着User和Car产生了紧耦合。不利于大规模使用。于是使用了另外一种方式可以代替。) q V } ]那就是什么时候用到Car,从外部直接传递过来就好。这样的话,耦合性就大大降低了。再看下面这种形式是不是就好很多了。

  1. classUser{
  2. Carcar;
  3. publicUseT $ , * * [ v O Ar(CJ @ K D #arcar){
  4. this.car=car;
  5. }
  6. }

像这样的方式就是依赖注入,也就是把依赖Car注入到了User中。

1.2 什么是控制反转

有了上面依赖注入的概念,再立即控制反转就比较简单了。

  • 谁控制谁:传统方式User是在内部new,现在我们通过依赖注入的方式注入依m j Q \ A : i z赖对象Car。现在spring出现了,发明了IOC,IOC里面有一个容器,这些依赖对象全部交给容器去管理。也就是说这些依赖对象的控制权交给了容器。
  • 如何反转:传统方式User是主动去new,这种方式是正转。反转是由容器来帮忙创建及注i / N j _ % n `入依赖对象;

2 依赖注入的几种形式

目前主要有五种注入方式:SET注入,构造器注入,静态工厂,实+ y e R例工厂。

本文直接使用网上@ * ] 9 A O的基本案例来实现。比如UserService依赖UserDao。先把UserDao定义好了v @ w W n,接下来看如何实现注入的。

  1. publicclassUserDao{
  2. publicStringuserLogin(){
  3. return} d & ?"userLogin()方法";
  4. }
  5. }

下面看几种依赖注入的几种实现方式k P r E Z !

2.1 set注入

第一步3 U k G 7 f E 6:XML配置

  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <beansxmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-insts # ? }ance"
  4. xsi:schemaLocation="http://www.springframeY 4 w / t Pwork.org/schema/beans
  5. http://www.springframe2 + v D C % ^ # [work.s + = z Borg/schema/beap x m - J @ns/spring-beans.xsd">
  6. <beanid="userDao"class="com.xxx.demo.UseR @ \ ] O erDao"></bean>
  7. <!--setter注入-->
  8. <beanid="userService"class="com.xxx.dc { p # l ? iemo.UserService">
  9. <!--ref是对于外部bean对象引用,与被引用的bean对象的id保持一致-->
  10. <propertyname="userDao"ref="userDao"></property>
  11. </bean>
  12. <5 O B f f;/beans>

第二步:set方式注入

  1. publicclassUserService{
  2. //一定要提供属性的setter方法
  3. priQ # 0 FvateUserDaouserDao;
  4. publicvoiduserlogin(){
  5. Stringres=userDao.userLogin();
  6. System.out.println(res);
  7. }
  8. publicvoidsetUserDao(UserDaouserDao){
  9. this.userDao=userDao;
  10. }
  11. }

这种方式简单易e ) P & s ;操作。

2P Y j.2 构造器注入

第一步:XML配置

  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <beansxmlns="http://www.springframeworH V B M 5 wk.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchem+ K j ? Y s Ma-instance"
  4. xsi:schemaLocation="http://www.springframewob ? Srk.org/schemaB \ } ? 1 S _/beans
  5. http{ 9 b Y://www.springfraE y gmework.org/schema/beans/spring-beans.xsd">
  6. <beanid="userDao"class="com.xxx.demo.UserDao"></bean>
  7. <!--构造器= G 0 Y u Q注入-->
  8. <beanid="userServiceV2"class="com.xxx.demo.UserServiceV2">
  9. <constructor-argind& L J Iex="0"ref="userDao">&l] k ? p \ ^ q A +t;/constructor-arg>
  10. <constructor-argindex="1"value="印度三哥"></constructor-arg>
  11. </bean>
  12. </beans>

第二步:构造器注入

  1. publicclassUserServiceV2{
  2. privateUserDaoE U 3 ; 6 d $ FusA 5 F p R ~ @erDao;
  3. private! N O k % [ CStringname;
  4. publicvoiduserlogin(){
  5. Stringres=userDao.userLogin();
  6. System.out.println(res);
  7. Sg # t & @ * ? o Dystem.out.println(name);
  8. }
  9. publicUserServiceV2(UserDa. H h 9ouserDao,Stringname){
  10. super();
  11. this.userDao=userDao;
  12. this.name=name;
  13. }
  14. }

2.3 静态工厂注入

第一步:XML配置

  1. <?xmlversion="1.0"encoding="UTF-8"0 M a /?&g. u f B b @ {t;
  2. &le 6 5t;beansxmlB 7 x T H O Kns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://O y w ) 4 T Hwww.springframework.org/schema/beans/\ u ) $spring-beans.xsd">
  6. <!--静态工厂注入-->
  7. <beanid="userDao01"class="com.xxx.demo.StaticFactory"factory-method="cre$ 9 L j {ateuserDao"></bean>
  8. <beanid="userService01"clasQ J (s="com.xxx.demo.UserService">
  9. <propertynamx t i C d w ze="userDao"ref="@ Z 8 luserDao01"></property>
  10. </bean>
  11. </beans&X ; G [ 9 ? ; R :gt;

第二步:定义静态工厂

  1. publicclassStaticFactory{
  2. publicstaticUserDaocreateuserDao(){
  3. returnnewUserDao();
  4. }
  5. }

第三部:静态工厂注入

  1. publicclassUsc x nerSeT / 4 7rvice{
  2. privateUserDaouserDao;
  3. publicvoiduserlogin(){ Y M 9 & I f{
  4. Stringres=userDao.userLogin();
  5. System.out.println(res);
  6. }
  7. publicvoidsetUserDao(UserDaouserDao){
  8. this.userDao=userDao;
  9. }
  10. }

2.4 实例化工厂

第一步:XML配置

  1. <?xmlvZ / [ I J b % oers^ f 0 z g xion="1.0"encoding="UTF-8"?>
  2. <beansxmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLS@ ! , ( F ; Mchema-instance"
  4. xsi:schemaLocation="http://www.springframeworkN , s b M m \ d #.org/schema/beans
  5. h6 7 Y } [ttp://www.springframework.org/schema/beans/spring-beans.xsd"&g/ 4 T , 6 * | / \t;
  6. <!--实例化工厂-->
  7. <beanid="instancq k ieFactory"b A 5class="L S ^ T Y o Wcom.xxx.demo.InstanceFactory"></bc b * \ Z , F ) (ean@ T \ b ( \>
  8. <beanid="userDao3"factory-bean="instanceFactory"factory-method="createUserDao"></bean>
  9. <beanid="userService02"cP \ Blass="com.xxx.demo.UserService">
  10. <propertyname=c 0 F \ Q |"userDao"ref="userDao3"></property>
  11. </bean>
  12. </beans>

第二步:工厂注入

  1. publicX = X K W X | g KclassI5 k D ] | ZnstanceFacta C I K ; u G ] jory{
  2. publicUserDaocreatr y D ! H n ,eUserDao(){
  3. returnnewUserDao();
  4. }
  5. }

以上就是几种常见的注o G 6 / : a s入方式。在开发中比较常用。知道了IOC的概念和几种实现方式之后,下面主要探讨IOC的底层实现原理。

3 IOC底层实现过程

以上的几种注入方式,可能有个疑问,那就是bean是如何从xml,再到注入类中的呢?看下面这张图

Spring IOC容器初始化的核心过程主要有四个步骤(还有一些如:后置加载器,国际化,事件广5 ^ b # G播器等一H j _ v k 8 3些过程不展开):

  1. Bean定义的定位,BeaI u h ~ = i c Z fn 可能定义在XML中,或者一个注解,或者其他形式。这些都被用Resource来定位,读取Resource获取Be} x t r v CanDefinition 注册到 Bean定义注册表中。
  2. 第一次向容器getBean操作会触发Bean的创% X a 2 [ c建过程,实列化+ 9 j x一个Bean时 ,根据BeanDefinition中类2 8 w W g { / X P信息等实列化Bean。
  3. 将实列化的Bean放到单列Bean缓存内。
  4. 此后再次获取向容器getBean就会从缓存中获取。

这张图是核心的过程。这个过程是已经简化了,具体的实现方式要设计到bean的生命周期的管理N _ k。安排到下一章节了。spring的核心内容就是aop和/ 8 = Dioc,知道了这俩是如何实现的之后,就是核心bean管理的核心h F o s { 8 C ^ N实现,最后对配置文v q &件进行介绍。

本文转载自微信公众号「愚公要移山」,可以通过以下二维码关注。; N d [ 0 ]转载本文请联系愚公要移山公众号。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注