《Spring框架IOC容器笔记---动力节点》

第一个Spring项目

  步骤:
  1、新建java project
  2、导入必备的jar
    1>spring的核心:spring-beans.jar,spring-core.jar,spring-context.jar,spring-expression.jar
    2>日志:commons-logging.jar
  可选的有日志实现:log4j.jar 单元测试:junit.jar
                    在这里插入图片描述
  3、定义接口和实现类,与没有使用框架一样定义
在这里插入图片描述
  4、定义spring的配置文件
    1>加入约束文件spring-beans.xsd
    2>声明bean对象,即java对象
试想,如何让Spring知道你声明了SomeServiceImpl类,然后去创建对象呢?不管IOC是DL或者是DI方式实现,配置文件都是必不可少的。一般都是用applicationContext.xml命名,applicationContext.xml的配置参考xsd-config.html
        在这里插入图片描述
拷贝这一段到applicationContext.xml
在这里插入图片描述
  5、定义测试类,在代码中使用spring,需要创建接口ApplicationContext,表示spring框架。
在这里插入图片描述
   < bean id = “someService” class=“com.bjpowernode.service.SomeServiceImpl” > < /bean>的作用就相当于
SomeService someService = new com.bjpowernode.service.SomeServiceImpl();
  main函数获取bean对象测试:注意此时我的applicationContext.xml放在src下的根目录,所以直接使用ClassPathXmlApplicationContext创建ApplicationContext。若applicationContext.xml放在某个磁盘目录,则用FileSystemXmlApplicationContext创建。
在这里插入图片描述
若applicationContext.xml直接放在项目的根目录下,即和src是同级,需要使用FileSystemXmlApplicationContext读取配置文件
在这里插入图片描述

getBean()源码分析

右键getBean open Implementation,跑到AbstractBeanFactory中查看源码,
在这里插入图片描述
  查看getBean
在这里插入图片描述
  可以发现bean是getObjectForBeanInstance获得然后返回的
在这里插入图片描述
  getObjectForBeanInstance中调用了getObjectFromFactoryBean,而getObjectFromFactoryBean中object是从FactoryBeanRegistrySupport中的factoryBeanObjectCache中get得到的。
在这里插入图片描述
而果然,factoryBeanObjectCache是一个Map,并且是一个ConcurrentHashMap。
在这里插入图片描述
关键结论:我们从容器中获取一个bean对象用applicationContext的对象的getBean(“bean的id名”)方法实现,获取bean对象是BeanFactory类通过工厂模式实现,所有的bean对象其实都放在一个ConcurrentHashMap中,getBean其实就是从这个Map中getObject,这也就是为什么applicationContext.xml中的bean id名必须唯一的原因

在创建ApplicationContext容器时会创建所有配置文件中的 bean对象

  在SomeServiceImpl中添加无参构造函数。
        在这里插入图片描述
  测试ApplicationContext容器创建时,bean对象已经创建了。
在这里插入图片描述
并且是一个bean标签会创建一个对象,例如新增一个bean标签
在这里插入图片描述
再次运行,你会发现无参构造器被执行了两次,说明创建了两个对象。
在这里插入图片描述
同时,可以获取容器关于bean对象的信息
在这里插入图片描述

非联网下的约束文件的配置

  spring的约束文件用于作为数据标签属性的验证。联网情况下会自动下载xsd约束文件。
在这里插入图片描述
  本地中在:spring-framework-4.0.0.RELEASE\schema\beans中
在这里插入图片描述
复制http://www.springframework.org/schema/beans/spring-beans.xsd ,然后到windows–perference–xml catalog中添加,并指定本地的xsd
在这里插入图片描述
此时你打一个<就会有提示:
                    在这里插入图片描述

Bean的装配

  bean的装配其实就是bean对象的创建,属性的赋值,然后把创建好的对象赋值给程序
  Spring框架默认是使用bean的无参构造方法创建对象,若bean类没有无参构造方法,会提示错误。
在这里插入图片描述
在这里插入图片描述

容器bean中的作用域

  可以通过配置Spring配置文件为bean指定作用域,Spring支持5种作用域。

  • singleton:单例模式,整个Spring容器中singleton定义的bean是单例的。优点:获取对象速度快,缺点占内存。
  • prototype:原型模式,每次使用getBeans方法获取的bean是一个新的实例。优点,不占内存,但是获取对象速度相比单例作用域模式慢
  • request:对于每次http请求,都会产生一个不同的bean实例
  • session:对于每个不同的http session,都会产生一个不同的bean实例

注意:

  • 对于socpe值是request、session只有在web应用中使用了Spring,该作用域才有效
  • 对于scope值是singleton的单例模式,该bean是在容器创建时即被装配好的
  • 对于socpe值为prototype的原型模式,bean实例是在代码中使用该bean才进行装配的

  singleton实例:
在这里插入图片描述
注意即使不加singleton,也是默认为单例的
在这里插入图片描述
prototype:原型模式实例
在这里插入图片描述
在这里插入图片描述
  并且prototype:原型模式下,容器创建时并不会创建bean对象,而是在执行getBean()方法时才创建对象,把对象的创建时间延迟了。
在这里插入图片描述

可定制bean声明始末方法

  可以自定义方法在spring bean对象的创建与销毁过程中。定制的过程:

  1. 在java类中定义方法,方法的原型:public void 方法名自定义(无参){ …}
  2. 在定义bean对象的时候,告诉spring的两个方法存在

首先先自定义新增两个bean对象在容器创建的初始化、销毁方法:
在这里插入图片描述
  告诉Spring这两个方法是这个bean的init-method ,destroy-method。
在这里插入图片描述
  Spring容器销毁时:
在这里插入图片描述

Spring IOC容器采用DI方式实现

基于XML配置文件的DI

  注入方式即赋值方法有设值注入(掌握)、构造注入(理解)。

  • 设值注入:调用java类的set方法,给属性赋值
  • 构造注入:调用java类的有参构造方法,创建对象的同时,给属性赋值

简单类型设值注入

简单类型:spring中把String和java的戒备数据类型,称为简单类型
简单类型的设值注入:语法
< bean id = “xxx” class=“yyy” >
  < property name = “属性值” value = “简单类型的属性值”/>
  < propety name = "属性值 " value = “简单类型的属性值”/>
  …
</ bean>
自定义一个Student bean:
在这里插入图片描述
配置XML信息,进行属性注入:
在这里插入图片描述
执行结果:
在这里插入图片描述
  若bean没有set方法,会报错:org.springframework.beans.NotWritablePropertyException 。
  若student bean中有setSex()方法,并且在配置文件中property指定了,但是student bean没有sex属性,仍然不影响容器调用setSex方法。

引用类型的设置注入

语法有两种
语法1:使用ref作为属性
  < bean id = “xx” class = “yy”>
    < property name = “属性名” ref ="bean 的id "/>
  </ bean>
语法2:使用ref作为子标签
  < bean id = “xx” class = “yy”>
    < property name = “属性名”>
      < ref = “bean的id” />
    < /property>
  </ bean>
使用ref作为属性 实例:Student中有学校类School
            在这里插入图片描述
学校类School:
            在这里插入图片描述
ref作为属性的配置:
在这里插入图片描述
运行结果:
在这里插入图片描述

ref作为子标签:
在这里插入图片描述

构造注入:调用类的有参构造方法,在构造方法中属性赋值,使用< constructor-arg >标签,一个构造方法的参数对应一个< constructor-arg >标签

构造注入需要bean有有参构造器:
在这里插入图片描述
配置文件:
在这里插入图片描述
运行结果:
在这里插入图片描述
构造注入可以用index 来表示其 bean的有参构造函数中的参数:
在这里插入图片描述
当然也可以将Index省略,但是此时顺序不能调换:
在这里插入图片描述
集合类型的注入:什么类型的属性就用什么类型的子标签,list集合用< list>标签。Properties的成员变量,用 < props>标签。

<bean id="department" class="com.LHB.collection.Department">
       <property name="name" value="财务部门" />
       <!-- 给数组注入值 -->
       <property name="empName">
           <list>
               <value>小米</value>
               <value>小明</value>
               <value>小四</value>
           </list>
       </property>
       
       <!-- 给list注入值 可以有相同的多个对象  -->
       <property name="empList">
           <list>
               <ref bean="emp1" />
               <ref bean="emp2"/>
           </list>
       </property>
       <!--set注入值 不能有相同的对象 -->
       <property name="empSets">
           <set>
               <ref bean="emp1" />
               <ref bean="emp2"/>
           </set>
       </property>
       
       <!-- 给map注入值 只要map中的key值不一样就可以装配value -->
       <property name="empMap">
           <map>
               <entry key="1" value-ref="emp1" />
               <entry key="2" value-ref="emp2" />
           </map>
       </property>
       
       <!-- 给属性集合配置 -->
       <property name="pp">
           <props>
               <prop key="pp1">hello</prop>
               <prop key="pp2">world</prop>
           </props>
       </property>
   </bean>
   <bean id="emp1" class="com.LHB.collection.Employee">
       <property name="name">
           <value>北京</value>
       </property>
   </bean>
    <bean id="emp2" class="com.LHB.collection.Employee">
       <property name="name">
           <value>天津</value>
       </property>
   </bean>

引用类型的自动注入

  1. byName方式:当配置文件中被调用者Bean的id值与代码中调用者Bean类的属性名相同时,可使用byName方式,让容器自动将被调用者Bean注入给调用者Bean容器是通过调用者的Bean类的属性名与配置文件的被调用者bean的id进行比较而实现自动注入的。
    在这里插入图片描述
  2. 使用byType方式自动注入,要求:配置文件中被调用者bean的。class属性指定的类,要与代码中调用者Bean类的某域属性类型同源。即要么相同,要么有is-a关系(子类,或是实现类)。但这样的同源的被调用bean只能有一个。多于一个,容器就不知该匹配哪一个了。此处的同源关系有含义:
    1、java类引用类型的数据类型和< bean> 的class一样的
    2、java类引用类型的数据类型和< bean>的class是父类和子类的关系
    3、java类中引用类型的数据类型和< bean> 的class是接口或实现类关系
    下面的School在配置文件中,如果还有School的子类,就不能用Type方式注入,要保证唯一性。
    在这里插入图片描述

使用Spring EL语言注入

  SPEL Spring Expression Language即Spring EL表达式语言。即,在Spring配置文件中为Bean的属性注入值时,可直接使用SPEL表达式计算的结果。SPEL表达式以#开头,后跟一对大括号。用法:。其文档中有其用法举例。在Spring框架解压目录\docs\spring-framework-reference\htmlsingle\index.html中。Ctrl+F,对SPEL
进行检索。

基于注解的DI

  与基于XML配置文件DI方式区别之一,需要在配置文件中声明组件扫描器,< context:compoent-scan base-package></context:component-scan> 表明用注解方式创建对象
@Component: 需要在类上使用注解@Component,该注解的value属性用于指定该bean的id值
@Repository :用于对DAO实现类进行注解
@Service:用于对Service实现类进行注解
@Controller :用于对Controller实现类进行注解
在这里插入图片描述
Bean的作用域@Scope:需要在类上使用注解@Scope,其value属性用于指定作用域。默认为singleton
在这里插入图片描述
基本类型属性注入@Value: 使用该注解完成属性注入时,类中无需setter。当然,若属性有setter,则也可将其加到setter上。
在这里插入图片描述
按类型注入域属性@Autowired:需要在域属性上使用注解@Autowired,该注解默认使用按类型自动装配Bean的方式。使用该注解完成属性注入时,类中无需setter。当然,若属性有setter,则也可将其加到setter上
在这里插入图片描述
按名称注入域属性@Autowired与@Qualifier:
在这里插入图片描述
域属性注解@Resource:@Resource注解既可以按名称匹配Bean,也可以按类型匹配Bean。
按类型注入域属性:在这里插入图片描述
按名称注入域属性:

在这里插入图片描述

Spring工程指定多个Spring配置文件

   在实际应用里,随着应用规模的增加,系统中Bean数量也大量增加,导致配置文件变得非常庞大、臃肿。为了避免这种情况的产生,提高配置文件的可读性与可维护性,可以将Spring配置文件分解成多个配置文件。

平等关系配置文件

   将所有配置文件的路径定义为一个String数组,并将其作为容器初始化参数出现。其将与可变参的容器构造器匹配。各个配置文件直接为并列关系,不分主次。
               在这里插入图片描述
在这里插入图片描述

包含关系

   各配置文件中有一个总文件,总配置文件将各其它子文件通过引入。在Java代码中只需要使用总配置文件对容器进行初始化即可。
                     在这里插入图片描述
在这里插入图片描述

使用junit4测试Spring

   参考 动力节点 Spring4笔记。

猜你喜欢

转载自blog.csdn.net/weixin_41262453/article/details/90722306