Spring知识点总结(二)之Spring IOC

1.创建bean类,并在spring中进行配置交由spring来管理1. IOC(DI) - 控制反转(依赖注入)
    所谓的IOC称之为控制反转,简单来说就是将对象的创建的权利及对象的生命周期的管理过程交由Spring框架来处理,从此在开发过程中不再需要关注对象的创建和生命周期的管理,而是在需要时由Spring框架提供,这个由spring框架管理对象创建和生命周期的机制称之为控制反转。而在 创建对象的过程中Spring可以依据配置对对象的属性进行设置,这个过称之为依赖注入,也即DI。
    
2. IOC的入门案例
    a. 下载Spring
        访问Spring官网,下载Spring相关的包
    b. 解压下载好的压缩包
        其中包含着Spring的依赖包
    c. 创建一个java项目
        spring并不是非要在javaweb环境下才可以使用,一个普通的java程序中也可以使用Spring。
 d.导入Spring的libs目录下IOC相关的jar包

  

e. 创建Spring的配置文件
  Spring采用xml文件作为配置文件,xml文件名字任意,但通常都取名为applicationContext.xml,通常将该文件放置在类加载的目录里下  (src目录),方便后续使用。

  f.创建bean类,并在spring中进行配置交由spring来管理

            1     <?xml version="1.0" encoding="UTF-8"?>
            2     <beans xmlns="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://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
            6             
            7             <bean id="person" class="cn.tedu.beans.Person"></bean>
            8             
            9     </beans>

g. 在程序中通过Spring容器获取对象并使用

         1   public class Person_Test {
            2             @Test
            3             /**
            4              * SpringIOC的入门案例
            5              */
            6             public void  test1(){
            7                     ApplicationContext context =
            8                                     new ClassPathXmlApplicationContext("applicationContext.xml");
            9                     Person p = (Person) context.getBean("person");
           10                     p.say();
           11             }
           12     }

3. IOC的实现原理
    在初始化一个Spring容器时,Spring会去解析指定的xml文件,当解析到其中的<bean>标签时,会根据该标签中的class属性指定的类的全路径名,通过反射创建该类的对象,并将该对象存入内置的Map中管理。其中键就是该标签的id值,值就是该对象。
    之后,当通过getBean方法来从容器中获取对象时,其实就是根据传入的条件在内置的Map中寻找是否有匹配的键值,如果有则将该键值对中保存的对象返回,如果没有匹配到则抛出异常。
    
    由此可以推测而知:
        默认情况下,多次获取同一个id的bean,得到的将是同一个对象。
        即使 是同一个类,如果配置过多个<bean>标签具有不同的id,每个id都会在内置Map中有一个键值对,其中的值是这个类创建的不同的对象
        同一个<beans>标签下不允许配置多个同id的<bean>标签,如果配置则启动抛异常
    
4. IOC获取对象的方式
    通过context.getBeans()方法获取bean时,可以通过如下两种方式获取:
        传入id值
        传入class类型
    通过class方式获取bean时,如果同一个类配置过多个bean,则在获取时因为无法确定到底要获取哪个bean会抛出异常。
    而id是唯一的,不存在这样的问题,所以建议大家尽量使用id获取bean。

        1     @Test
        2     /**
        3      * SpringIOC获取bean的方式
        4      */
        5     public void  test3(){
        6             /*
        7              <bean id="person" class="cn.tedu.beans.Person"></bean>
        8              */
        9             /*
       10              <bean id="person" class="cn.tedu.beans.Person"></bean>
       11              <bean id="personx" class="cn.tedu.beans.Person"></bean>
       12              */
       13             ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
       14             //--通过id获取
       15             Person p1 = (Person) context.getBean("person");
       16             p1.say();
       17             //--通过class获取
       18             Person p2 = context.getBean(Person.class);
       19             p2.say();
       20     }

5. 别名标签
    在 Spring中提供了别名标签<alias>可以为配置的<bean>起一个别名,要注意的是这仅仅是对指定的<bean>起的一个额外的名字,并不会额外的创建对象存入map。
        <alias name="要起别名的bean的id"  alias="要指定的别名"/>

        1     @Test
        2     /**
        3      * SpringIOC中bean别名
        4      */
        5     public void  test4(){
        6             /*
        7                     <bean id="person" class="cn.tedu.beans.Person"></bean>
        8                     <alias name="person" alias="personx"/>
        9              */
       10             ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
       11             //--通过id获取
       12             Person p1 = (Person) context.getBean("personx");
       13             p1.say();
       14     }

6. Spring创建对象的方式
    a. 通过类的无法构造方法创建对象
        在入门案例中使用的就是这种方式。当用最普通方式配置一个<bean>时,默认就是采用类的无参构造创建对象。在Spring容器初始化时,通过<bean>上配置的class属性反射得到字节码对象,通过newInstance()创建对象

                1     Class c = Class .forName("类的全路径名称")
                2     Object obj = c.newInstance()
        这种方式下spring创建对象,要求类必须有无参的构造,否则无法通过反射创建对象,会抛出异常。
                1     package cn.tedu.beans;
                2
                3     public class Person {
                4             public Person(String arg) {
                5                     System.out.println("Person的无参构造执行了。。。");
                6             }
                7             public void say(){
                8                     System.out.println("person hello spring~");
                9             }
               10     }
               11     @Test
               12     /**
               13      * SpringIOC 创建对象方式 1 - 通过无参构造方法创建对象
               14      */
               15     public void test5(){
               16             /*
               17                      <bean id="person" class="cn.tedu.beans.Person"></bean>
               18              */
               19             ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
               20             Person p  = (Person) context.getBean("person");
               21             p.say();
               22     }

b. 通过静态工厂创建对象
        很多的时候,我们面对的类是无法通过无参构造去创建的,例如该类没有无参构造、是一抽象类 等等情况 ,此时无法要求spring通过无参构造创建对象,此时可以使用静态工厂 方式创建对象。

            1     public class CalendarStaticFactory {
            2             public static Calendar getCalendar(){
            3                     return Calendar.getInstance();
            4             }
            5     }
            1     <?xml version="1.0" encoding="UTF-8"?>
            2     <beans xmlns="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://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
            6
            7             <bean id="calendar"  class="cn.tedu.factory.CalendarStaticFactory" factory-method="getCalendar"></bean>
            8
            9     </beans>
            1     @Test
            2     /**
            3      * SpringIOC 创建对象方式 2 - 静态工厂
            4      */
            5     public void test6(){
            6             ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            7             Calendar calendar = (Calendar) context.getBean("calendar");
            8             System.out.println(calendar);
            9     }

c. 实例工厂创建对象
        实例工厂也可以解决类是无法通过无参构造创建的问题,解决的思路和静态 工厂类似,只不过实例工厂提供的方法不是静态的。spring需要先创建出实例工厂的对象,在调用实例工厂对象上指定的普通方法来创建对象。所以实例工厂也需要配置到Spring中管理。

            1     package cn.tedu.factory;
            2
            3     import java.util.Calendar;
            4
            5     public class CalendarFactory {
            6             public Calendar getCalendar(){
            7                     return Calendar.getInstance();
            8             }
            9     }
            1     <?xml version="1.0" encoding="UTF-8"?>
            2     <beans xmlns="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://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
            6
            7             <bean id="calendarFactory"  class="cn.tedu.factory.CalendarFactory"></bean>
            8             <bean id="calendar" factory-bean="calendarFactory" factory-method="getCalendar"/>
            9
           10     </beans>
            1     @Test
            2     /**
            3      * SpringIOC 创建对象方式 3 - 实例工厂
            4      */
            5     public void test7(){
            6             ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            7             Calendar calendar = (Calendar) context.getBean("calendar");
            8             System.out.println(calendar);
            9     }

d. Spring工厂创建对象
        Spring内置了工厂接口,也可以通过实现这个接口来开发Spring工厂,通过这个工厂创建对象。

            1     package cn.tedu.factory;
            2
            3     import java.util.Calendar;
            4
            5     import org.springframework.beans.factory.FactoryBean;
            6
            7     public class CalendarSpringFactory implements FactoryBean<Calendar>{
            8
            9             /**
           10              * Spring工厂生产对象的方法
           11              */
           12             @Override
           13             public Calendar getObject() throws Exception {
           14                     return Calendar.getInstance();
           15             }
           16
           17             /**
           18              * 获取当前工厂生产的对象的类型的方法
           19              */
           20             @Override
           21             public Class<?> getObjectType() {
           22                     return Calendar.class;
           23             }
           24
           25             /**
           26              * Spring工厂生产对象时是否采用单例模式
           27              * 如果返回true,则在spring中该对象只创建一次 后续 重复使用
           28              * 如果返回false,则每次获取该bean 都重新 创建对象
           29              */
           30             @Override
           31             public boolean isSingleton() {
           32                     return true;
           33             }
           34
           35     }
            1     <?xml version="1.0" encoding="UTF-8"?>
            2     <beans xmlns="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://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
            6
            7             <bean id="calendar" class="cn.tedu.factory.CalendarSpringFactory"></bean>
            8
            9     </beans>
            1     @Test
            2     /**
            3      * SpringIOC 创建对象方式 3 - spring工厂
            4      */
            5     public void test8(){
            6             /*
            7                     <bean id="calendar" class="cn.tedu.factory.CalendarSpringFactory"></bean>
            8             */
            9             ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
           10             Calendar calendar = (Calendar) context.getBean("calendar");
           11             System.out.println(calendar);
           12     }

7. 单例和多例
    Spring容器管理的bean在默认情况下是单例的,也即,一个bean只会创建一个对象,存在内置 map中,之后无论获取多少次该bean,都返回同一个对象。
    
    Spring默认采用单例方式,减少了对象的创建,从而减少了内存的消耗。
    但是在实际开发中是存在多例的需求的,Spring也提供了选项可以将bean设置为多例模式。

         1     <?xml version="1.0" encoding="UTF-8"?>
            2     <beans xmlns="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://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
            6
            7             <!--
            8                     scope属性控制当前bean的创建模式:
            9                             singleton:则当前bean处在单例模式中,默认就是此模式
           10                             prototype:则当前bean处在多例模式中
           11              -->
           12             <bean id="cart" class="cn.tedu.beans.Cart" scope="prototype"></bean>
           13
           14     </beans>
    

bean在单例模式下的生命周期:
        bean在单例模式下,spring容器启动时解析xml发现该bean标签后,直接创建该bean的对象存入内部map中保存,此后无论调用多少次getBean()获取该bean都是从map中获取该对象返回,一直是一个对象。此对象一直被Spring容器持有,直到容器退出时,随着容器的退出对象被销毁。
    
    bean在多例模式下的生命周期:
        bean在多例模式下,spring容器启动时解析xml发现该bean标签后,只是将该bean进行管理,并不会创建对象,此后每次使用 getBean()获取该bean时,spring都会重新创建该对象返回,每次都是一个新的对象。这个对象spring容器并不会持有,什么销毁取决于使用该对象的用户自己什么时候销毁该对象。
    
        实验:通过断点调试模式 ,观察spring单例和多例的bean执行构造的过程
                1     略

8. 懒加载机制
    Spring默认会在容器初始化的过程中,解析xml,并将单例的bean创建并保存到map中,这样的机制在bean比较少时问题不大,但一旦bean非常多时,spring需要在启动的过程中花费大量的时间来创建bean 花费大量的空间存储bean,但这些bean可能很久都用不上,这种在启动时在时间和空间上的浪费显得非常的不值得。
    所以Spring提供了懒加载机制。所谓的懒加载机制就是可以规定指定的bean不在启动时立即创建,而是在后续第一次用到时才创建,从而减轻在启动过程中对时间和内存的消耗。
    懒加载机制只对单例bean有作用,对于多例bean设置懒加载没有意义。
    
    懒加载的配置方式:
        为指定bean配置懒加载

                1     <?xml version="1.0" encoding="UTF-8"?>
                2     <beans xmlns="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://www.springframework.org/schema/beans/spring-beans-3.2.xsd"
                6             >
                7
                8             <bean id="cart" class="cn.tedu.beans.Cart" lazy-init="true"></bean>
                9
               10     </beans>
        为全局配置懒加载
                1     <?xml version="1.0" encoding="UTF-8"?>
                2     <beans xmlns="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://www.springframework.org/schema/beans/spring-beans-3.2.xsd"
                6             default-lazy-init="true"
                7             >
                8
                9             <bean id="cart" class="cn.tedu.beans.Cart"></bean>
               10
               11     </beans>

**如果同时设定全局和指定bean的懒加载机制,且配置不相同,则对于该bean局部配置覆盖全局配置。
    
        实验:通过断点调试,验证懒加载机制的执行过程

    1     package cn.tedu.beans;
                2
                3     public class Cart {
                4             public Cart() {
                5                     System.out.println("Cart init...");
                6             }
                7     }
                1     <?xml version="1.0" encoding="UTF-8"?>
                2     <beans xmlns="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://www.springframework.org/schema/beans/spring-beans-3.2.xsd"
                6             >
                7
                8             <bean id="cart" class="cn.tedu.beans.Cart" lazy-init="true"></bean>
                9
               10     </beans>
                1     @Test
                2     /**
                3      * SpringIOC 懒加载机制
                4      */
                5     public void test10(){
                6             ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
                7             Cart cart1 = (Cart) context.getBean("cart");
                8             Cart cart2 = (Cart) context.getBean("cart");
                9             System.out.println(cart1 == cart2);
               10     }

9. 配置初始化和销毁的方法
    在Spring中如果某个bean在初始化之后 或 销毁之前要做一些 额外操作可以为该bean配置初始化和销毁的方法 ,在这些方法中完成要功能。
    
        实验:通过断点调试模式,测试初始化方法 和 销毁方法的执行

     1     package cn.tedu.beans;
            2
            3     public class ProdDao {
            4
            5             public ProdDao() {
            6                     System.out.println("ProdDao 被创建。。。");
            7             }
            8
            9             public void init(){
           10                     System.out.println("init。。连接数据库。。。。。");
           11             }
           12
           13
           14             public void destory(){
           15                     System.out.println("destory。。断开数据库。。。。。");
           16             }
           17
           18             public void  addProd(){
           19                     System.out.println("增加商品。。");
           20             }
           21             public void  updateProd(){
           22                     System.out.println("修改商品。。");
           23             }
           24             public void  delProd(){
           25                     System.out.println("删除商品。。");
           26             }
           27             public void  queryProd(){
           28                     System.out.println("查询商品。。");
           29             }
           30     }
         1     <?xml version="1.0" encoding="UTF-8"?>
            2     <beans xmlns="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://www.springframework.org/schema/beans/spring-beans-3.2.xsd"
            6             >
            7
            8             <bean id="prodDao" class="cn.tedu.beans.ProdDao"
            9                     init-method="init" destroy-method="d y"></bean>
           10
           11     </beans>
            1     @Test
            2     /**
            3      * SpringIOC 初始化和 销毁方法
            4      */
            5     public void test11(){
            6             ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            7             ProdDao prodDao = (ProdDao) context.getBean("prodDao");
            8             prodDao.addProd();
            9             context.close();
           10     }
    

    **Spring中关键方法的执行顺序:
        在Spring创建bean对象时,先创建对象(通过无参构造或工厂),之后立即调用init方法来执行初始化操作,之后此bean就可以哪来调用其它普通方法,而在对象销毁之前,spring容器调用其destory方法来执行销毁操作。

原文地址:https://www.cnblogs.com/nanlinghan/p/9914898.html

时间: 2024-08-08 14:25:02

Spring知识点总结(二)之Spring IOC的相关文章

深入探索spring技术内幕(二): 剖析spring管理Bean的原理与配置

求二叉树的宽度和深度 给定一个二叉树,获取该二叉树的宽度和深度. 例如输入 a / \ b c / \ / \ d e f g 返回3. 详细描述: 接口说明 原型: int GetBiNodeInfo(BiNode &head, unsigned int *pulWidth, unsigned int *pulHeight) 输入参数: head 需要获取深度的二叉树头结点 输出参数(指针指向的内存区域保证有效): pulWidth 宽度 pulHeight 高度 返回值: 0 成功 1 失败

Spring知识点小结(二)

一.配置非自定义的Bean(数据源DataSource模型) DBCP数据源:        导入dbcp的jar包:dbcp+pool+connector                代码实现:            //创建数据源对象            BasicDataSource dataSource = new BasicDataSource();            //设置数据库的基本参数            dataSource.setDriverClassName("

Spring学习(二)spring ioc注入的三种方式

一.spring ioc注入有哪三种方式: a setter 原理 : 在目标对象中,定义需要注入的依赖对象对应的属性和setter方法:"让ioc容器调用该setter方法",将ioc容器实例化的依赖对象通过setter注入给目标对象,封装在目标对象的属性中. b 构造器 原理 : 为目标对象提供一个构造方法,在构造方法中添加一个依赖对象对应的参数.ioc容器解析时,实例化目标对象时会自动调用构造方法,ioc只需要为构造器中的参数进行赋值:将ioc实例化的依赖对象作为构造器的参数传入

Spring的学习二(Spring Ioc和DI,AOP简介)

一:Spring Ioc,DI,AOP简介 IOC控制反转:将原本在程序中手动创建对象的控制权,交由Spring框架来管理 原理: 读取标注或者配置文件,看看Shoe依赖的是哪个Source,拿到类名 使用反射的API,基于类名实例化对应的对象实例 将对象实例,通过构造函数或者 setter,传递给 ShoeShop 以前是我们自己new对象(自己买材料,工具自己做鞋子),现在只要告诉IOC这个容器(鞋店),他自动给你new好,你直接取对象就好了,省去了我们自己new对象的过程 DI:依赖注入:

Spring核心技术(二)——Spring的依赖及其注入

本文将继续前文,描述Spring IoC中的依赖处理. 依赖 一般情况下企业应用不会只有一个对象(或者是Spring Bean).甚至最简单的应用都要多个对象来协同工作来让终端用户看到一个完整的应用的.下一部分将解释开发者如何从仅仅定义单独的Bean,到让这些Bean在一个应用中协同工作. 依赖注入 依赖注入是一个让对象只通过构造参数,工厂方法的参数或者配置的属性来定义他们的依赖的过程.这些依赖也是对象所需要协同工作的对象.容器会在创建Bean的时候注入这些依赖.整个过程完全反转了由Bean自己

【spring教程之二】spring注入xml中带参数的构造函数

1.续上文,如果想在注入bean文件的时候,传入参数到构造函数中.主要需要修改的就是spring.xml配置文件中的配置方法. <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-insta

Spring(十二)Spring整合Mybatis

首先第一步引依赖: <!--Mybatis+Spring整合--><dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.1</version></dependency><!-- Spring整合JavaWeb的包 --><dependency&

Spring学习(二)Spring Bean装配

Bean的作用域 ========================== bean有五种作用域 scopesingleton : 单例,指一个Bean容器中只存在一份prototype : 每次请求(每次使用)创建新的实例,destroy方式不生效request : 每次http请求创建一个实例且仅在当前request内有效sesson : 同上,每次http请求创建,当前session内有效global session : 基于portlet的web中有效(portlet定义了 global s

Spring Boot(十二):Spring Boot 如何测试打包部署

有很多网友会时不时的问我, Spring Boot 项目如何测试,如何部署,在生产中有什么好的部署方案吗?这篇文章就来介绍一下 Spring Boot 如何开发.调试.打包到最后的投产上线. 开发阶段 单元测试 在开发阶段的时候最重要的是单元测试了, Spring Boot 对单元测试的支持已经很完善了. 1.在 pom 包中添加 spring-boot-starter-test 包引用 <dependency> <groupId>org.springframework.boot&