• spring基础——IoC(二)


    1、IoC是什么

      IOC——Inversion of Control,即控制反转,不是什么技术,而是一种设计思想。在Java开发中,IoC意味着将你设计好的对象交给容器控制,而不是传统的直接在你的对象内部控制。

    • 谁控制谁,控制什么:传统的JavaSE程序设计,我们直接在对象内部通过new关键字进行对象的创建,是程序主动去创建依赖的对象;而IoC有一个专门的容器来创建对象,即由IoC容器来控制对象的创建;谁控制谁?当然是IoC容器控制对象;控制什么?主要控制了外部资源的获取(不只对象包括比如文件等)。
    • 为何是反转,那些方面反转:有反转就有正转,传统应用程序是由我们自己在对象中主动控制直接获取依赖对象,也就是正转;而反转则是由容器帮忙创建及注入依赖对象;为何是反转?因为由容器帮助我们查找及注入依赖对象。对象只是被动的接受依赖对象,所以是反转。

                

    2、DI是什么

      DI——Dependency Injection,即依赖注入,是组件之间的依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件儿中。依赖注入的目的并非为软件系统带来更多的功能,而是为了提升组件的复用性。

    • 谁依赖谁:当然是某个IoC容器管理对象依赖于容器,“被注入对象的对象”依赖于“依赖对象”。
    • 为什么需要依赖:容器管理对象需要IoC容器来提供对象需要的外部资源。
    • 谁注入谁:很明显是IoC容器注入某个对象,也就是注入依赖对象。
    • 注入了什么:就是注入某个对象需要的外部资源

      IoC和DI其实它们是同一个概念的不同角度描述,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”

    3、IoC容器

      IoC容器就是拥有依赖注入功能的容器,IoC容器负责实例化,定位,配置应用程序中的对象及监理这些对象之间的依赖。应用程序无需再直接通过new关键字创建对象,应用程序由IoC容器进行组装。在spring中BeanFactory是IoC容器的实际代表者。

    4、Bean

      由IoC容器管理的那些组成应用程序的对象我们叫它bean,bean是由spring容器初始化,装配及管理的对象,除此之外没有什么不同。IoC容器实例化管理bean需要配置元数据,在spring中由BeanDefinition代表。

    5、详解IoC容器

      在spring中IoC容器的带包就是org.springframework.beans包中的BeanFactory接口,BeanFactory接口提供了IoC容器最基本的功能;而org.springframework.context包下的ApplicationContext接口扩展了BeanFactory,还提供了与spring aop集

      成、国际化处理、事件传播及提供不同层次的Context实现。简单说就是BeanFactory提供了IoC容器最基本的功能,而ApplicationContext则增加了更多企业级功能支持。ApplicationContext完全集成BeanFactory,因而BeanFactory所具有的

      语义也适用于ApplicationContext。

      容器实现一览:

        XMLBeanFactory:BeanFactory实现,提供了基本的IoC功能,可以从classpath或文件系统获取资源:

    1 File file = new File("fileSystemConfig.xml");
    2 Resource resource = new FileSystemResource(file);
    3 BeanFactory beanFactory = new XmlBeanFactory(resource);
    4 
    5 Resource resource = new ClassPathResource("classpath.xml");
    6 BeanFactory beanFactory = new XmlBeanFactory(resource);

        ClassPathXmlApplicationContext:ApplicationContext实现,从classpath获取配置文件:

    1 BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath.xml");

        FileSystemXmlApplicationContext:ApplicationContext实现,从文件系统获取配置文件:

    1 BeanFactory beanFactory = new FileSystemXmlApplicationContext("fileSystemConfig.xml");

        ApplicationContext接口获取bean方法简介:

    1 Object getBean(String name)                   //根据名称返回一个Bean,客户端需要自己进行类型转换;
    2 T getBean(String name, Class<T> requiredType) //根据名称和指定的类型返回一个Bean,客户端无需自己进行类型转换,如果类型转换失败,容器抛出异常;
    3 T getBean(Class<T> requiredType)              //根据指定的类型返回一个 Bean,客户端无需自己进行类型转换,如果没有或有多于一个Bean存在容器将抛出异常;
    4 Map<String, T> getBeansOfType(Class<T> type)  //根据指定的类型返回一个键值为名字和值为Bean对象的Map,如果没有Bean对象存在则返回空的Map

    6、IoC容器如何工作  

    • 准备配置文件:在配置文件中声明bean定义也就是为bean配置元数据。
    • 由IoC容器解析元数据:IoC容器的Bean Reader读取并解析配置文件,根据定义生成BeanDefinition配置元数据对象,IoC容器根据BeanDefinition进行实例化、配置及组装bean。
    • 实例化IoC容器:由客户端实例化容器,获取需要的bean。

      

    7、IoC容器配置使用

      一般配置文件如下

    1 <beans>
    2  <import resource="resource1.xml"/>
    3  <bean id="bean1" class=""></bean>
    4  <bean id="bean2" class=""></bean>
    5  <bean name="bean2" class=""></bean>
    6  <alias alias="bean3" name="bean2"/>
    7  <import resource="resource2.xml"/>
    8 </beans>
    • bean标签主要用来进行bean定义;
    • alias用于定义bean别名;
    • import用于导入其他配置文件的bean定义这个是为了加载多个配置文件,当然也可以把这些配置文件构造为一个数组(new String[]{“config1.xml”,“config2.xml”})传给ApplicationContext实现进行多个配置文件加载。

      7.1 bean的配置

        spring IoC容器目的就是管理bean,这些bean将根据配置文件的定义进行创建,而bean定义在容器内部由BeanDefinition对象表示,该对象主要有以下含义:

          。全限定类名:用于定义bean的实现类

          。bean行为定义:这些定义了bean在容器中的行为;包括作用域(单例,原型创建)、是否惰性初始化及生命周期

          。bean创建方式定义:说明是通过构造器还是工厂方法创建bean

          。bean之间关系定义:即对其他bean的引用,也就是依赖关系定义

        bean不仅是只能通过配置方式创建,某些SingletonBeanRegistry接口实现类实现也允许将那些非BeanFactory创建、已有的用户对象注册到容器中,这些对象必须是共享的,不过建议采用配置的方式定义。

      7.2 bean的命名

        每个bean可以有一个或多个id,在这里我们把第一个id称为“标识符”,其余的id称为“别名”;这些id在IoC容器中必须唯一。

        。不指定id,只配置必须得全限定类名

    1 <bean class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> 
    1 @Test
    2 public void test1() {
    3   BeanFactory beanFactory = new ClassPathXmlApplicationContext("chapter2/namingbean1.xml");
    4    //根据类型获取 bean
    5    HelloApi helloApi = beanFactory.getBean(HelloApi.class);
    6    helloApi.sayHello();
    7 }

        。指定id,必须在IoC容器中唯一

    1 <bean id="bean" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> 
    1 @Test
    2 public void test2() {
    3   BeanFactory beanFactory = new ClassPathXmlApplicationContext("chapter2/namingbean2.xml");
    4   //根据id获取bean
    5    HelloApi bean = beanFactory.getBean("bean", HelloApi.class);
    6    bean.sayHello();
    7 }

       。指定name,这样name就是标识符,标识符必须在IoC容器中唯一

    1 <bean name="bean" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> 
    1 @Test
    2 public void test3() {
    3    BeanFactory beanFactory =  new ClassPathXmlApplicationContext("chapter2/namingbean3.xml");
    4    //根据 name 获取 bean
    5   HelloApi bean = beanFactory.getBean("bean", HelloApi.class);
    6   bean.sayHello();
    7}

      。指定id和name,id是标识符,name是别名,同样标识符必须在IoC容器中唯一

    1 <bean id="bean1" name="alias1" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>
    2 <!-- 如果id和name一样,IoC容器能检测到,并消除冲突 -->
    3 <bean id="bean3" name="bean3" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> 
     1 @Test
     2 public void test4() {
     3   BeanFactory beanFactory = new ClassPathXmlApplicationContext("chapter2/namingbean4.xml");
     5    //根据id获取bean
     6   HelloApi bean1 = beanFactory.getBean("bean1", HelloApi.class);
     7   bean1.sayHello();
     8   //根据别名获取bean
     9   HelloApi bean2 = beanFactory.getBean("alias1", HelloApi.class);
    10   bean2.sayHello();
    11   //根据id获取bean
    12   HelloApi bean3 = beanFactory.getBean("bean3", HelloApi.class);
    13   bean3.sayHello();
    14   String[] bean3Alias = beanFactory.getAliases("bean3");
    15   //因此别名不能和id一样,如果一样则由IoC容器负责消除冲突
    16   Assert.assertEquals(0, bean3Alias.length);
    17 }

      。指定多个name,多个name用“,”、“;”、“ ”分割,第一个被作为标识符,其他的被作为别名

      。用alias标签指定别名,别名也必须在IoC容器中唯一

      注:bean的命名约定

        bean的命名必须遵循xml命名规范,但最好符合Java命名规范,由字母、数字、下划线组成驼峰命名。 

      7.3 实例化bean

        传统的应用程序可以通过new关键字和反射方式进行实例化,而spring IoC容器则需要根据bean定义里的配置元数据通过反射机制来创建bean。

        。使用构造器实例化bean

    • 使用空参构造函数进行定义
    1 <bean name="bean1" class="cn.javass.spring.chapter2.HelloImpl2"/>
    • 使用有参数构造函数进行定义,constructor-arg标签指定参数值,index表示参数位置,value表示常量值,也可以指定引用,指定引用使用ref来引用另一个bean定义
    1 <bean name="bean2" class="cn.javass.spring.chapter2.HelloImpl2">
    2    <!-- 指定构造器参数 -->
    3    <constructor-arg index="0" value="Hello Spring!"/>
    4 </bean>
     1 @Test
     2 public void testInstantiatingBeanByConstructor() {
     3   //使用构造器
     4   BeanFactory beanFactory = new ClassPathXmlApplicationContext("chapter2/instantiatingBean.xml");
     5   HelloApi bean1 = beanFactory.getBean("bean1", HelloApi.class);
     6   bean1.sayHello();
     7   HelloApi bean2 = beanFactory.getBean("bean2", HelloApi.class);
     8   bean2.sayHello();
     9 }    

        。使用静态工厂方式实例化bean

    1 <!-- 使用静态工厂方法 -->
    2 <bean id="bean3" class="cn.javass.spring.chapter2.HelloApiStaticFactory" factory-method="newInstance">
    3    <constructor-arg index="0" value="Hello Spring!"/>
    4 </bean>
     1 public class HelloApiStaticFactory {
     2    //工厂方法
     3   public static HelloApi newInstance(String message) {
     4     //返回需要的Bean实例
     5      return new HelloImpl2(message);
     6   }
     7 }
     8 @Test
     9 public void testInstantiatingBeanByStaticFactory() {
    10   //使用静态工厂方法
    11   BeanFactory beanFactory = new ClassPathXmlApplicationContext("chaper2/instantiatingBean.xml");
    12   HelloApi bean3 = beanFactory.getBean("bean3", HelloApi.class);
    13   bean3.sayHello();
    14 }

        。使用实例工厂方法实例化bean

    1 <!—1、定义实例工厂 Bean -->
    2 <bean id="beanInstanceFactory" class="cn.javass.spring.chapter2.HelloApiInstanceFactory"/>
    3 <!—2、使用实例工厂 Bean 创建 Bean -->
    4 <bean id="bean4" factory-bean="beanInstanceFactory" factory-method="newInstance">
    5   <constructor-arg index="0" value="Hello Spring!"></constructor-arg>
    6 </bean>
     1 public class HelloApiInstanceFactory {
     2   public HelloApi newInstance(String message) {
     3      return new HelloImpl2(message);
     4   }
     5 }
    6
    7 @Test 8 public void testInstantiatingBeanByInstanceFactory() { 9   //使用实例工厂方法 10   BeanFactory beanFactory = new ClassPathXmlApplicationContext("chapter2/instantiatingBean.xml"); 11   HelloApi bean4 = beanFactory.getBean("bean4", HelloApi.class); 12   bean4.sayHello(); 13 }

      通过以上例子我们发现只是配置不一样,从获取方式看完全一样没有任何不同。

      至此我们已经讲完了spring IoC容器基础部分,包括IoC容器概念,如何实例化容器,bean配置、命名及实例化,bean获取等等。

  • 相关阅读:
    laravel的workflow流程插件
    [php]laravel框架容器管理的一些要点
    laravel 自带消息notification通知
    laravel5.5的定时任务详解(demo)
    Laravel核心代码学习
    laravel 加载指定版本的mongodb
    Linux安装Composer
    composer全量镜像使用方法
    laravel在github地址
    node anyproxy ssi简易支持
  • 原文地址:https://www.cnblogs.com/ouhouki/p/9685693.html
Copyright © 2020-2023  润新知