zoukankan      html  css  js  c++  java
  • spring实战第二章小记-装配bean

    时间:2020/02/06

    一.思想

    1.创建应用对象之间协作关系的行为通常称为装配,这也是依赖注入(DI)的本质。

    对于上面这句话的个人理解:当我们在new一个对象时如果传入了别的对象作为参数(这个对象可能是引用数据类型也可能是基本数据类型),这时两个对象之间就形成了一种依赖关系,由于这种依赖关系的存在,两个对象之间就是一种强耦合的关系,而通过依赖注入可以降低两个对象之间的耦合度,注意,不是消除,如果两个对象之间没有耦合关系,那两个对象就是完全没有关系的。

    2.spring框架提供了三种主要的装配机制:

    • 在XML中进行显式配置
    • 在Java中进行显示配置
    • 隐式的bean发现机制和自动装配

    3.关于上面三种方式的优先级(作者的意思,你可以根据自己的喜爱选择):

    隐式的bean发现机制和自动装配>在Java中进行显示配置>在XML中进行显示装配

    4.spring从两个角度来实现自动化装配:

    • 组件扫描:spring会自动发现应用上下文中所创建的bean。
    • 自动装配:spring自动满足bean之间的依赖。

    5.自动装配:自动装配就是让spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在spring应用上下文中寻找匹配某个bean需求的其他bean。

    6.在进行显式配置时,JavaConfig是更好的方案,因为它更为强大、类型安全并且对重构友好。

    7.默认情况下,spring中的bean都是单例的。

    8.在XML中声明DI时,会有多种可选的配置方案和风格。具体到构造器注入,有两种基本的配置方案可供选择:

    • <constructor-arg>元素
    • 使用spring3.0所引入的c-命名空间

    9.对于DI来说,有的时候是指类型的装配——也就是将对象的引用装配到依赖于它们的其他对象之中。而有的时候,我们需要做的只是用一个字面量来配置对象(基本类型对象以及String类型对象)。

    10.在装配bean引用和字面量值方面,<constructor-arg>和c-命名空间的功能是相同的。但是c-命名空间无法将集合装配到构造器参数中。 

    11.该选择构造器注入还是属性注入(Setter方法注入)呢?作为一个通用的规则,对强依赖使用构造器注入,而对可选择的依赖使用属性注入。

    12.spring框架的核心是spring容器,整个容器中存放的东西可以看作key-value对,key是bean的id,value是bean的对象。

    二.在XML中进行显示装配

    1.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-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    </bean>

    2.使用XML来启用组件扫描,使用spring context命名空间的<context:component-scan>元素。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    
      <context:component-scan base-package="soundsystem"/>
    </beans>

    3.<bean>:  <bean>元素类似于JavaConfig中的@Bean注解。

    <bean class="sdnu.machi.one"/>

    创建这个bean的类通过class属性来指定,并且要使用全限定的类名。

    因为没有明确给定ID,所以这个bean将会根据全限定类名来进行命名。在上述代码中,bean的id将会是"sdnu.machi.one#0"。其中,"#0"是一个计数的形式,用来区分相同类型的其他bean。如果你声明了另外一个one,并且没有明确进行标识,那么它自动得到的id将会是”sdnu.machi.one#1"。

    通常来将更好的办法是借助id属性,为每个bean设置一个你自己选择的名字。

    当spring发现这个<bean>元素时,它将会调用one的默认构造器来创建bean。(如果这时没有默认构造函数会报错)。

    4.<constructor-arg>:  通过该元素可以在XML中实现依赖注入。如下

    <bean id="one" class="sdnu.machi.one">
        <constructor-arg ref="two" />
    </bean>

    当spring遇到这个<bean>元素时,它会创建一个one实例。<constructor-arg>元素会告知spring要将一个id为two的bean引用传递到one的构造器中(有参构造器)。

    该元素还有value属性,通过该属性表明给定的值要以字面量的形式注入到构造器中。

    5.c-命名空间: 它是在XML中更为简洁的描述构造器参数的方式。要使用它的话,必须要在XML的顶部声明其模式,如下:

    xmlns:c="http://www.springframework.org/schema/c"

    添加了命名空间和模式声明后,我们就可以使用它来声明构造器参数了,如下所示:

    <bean id="one" class="sdnu.machi.one" c:cd-ref="two"/>

    除了使用构造器参数名外,我们也可以使用参数在整个参数列表中的位置信息:

    c:_0-ref:"two"

    将参数的名称换成了“0”,也就是参数的索引,因为在XML中不允许数字作为属性的第一个字符,因此必须要添加一个下划线作为前缀。

    在这里因为只有一个构造器参数,所以我们还有另外一种方案——根部不用去标示参数:

    c:_-ref="two"

    如果要注入的是字面量(基本数据类型以及string类型),参考代码如下:

    c:_title="machi"
    c:_content="is a good boy"

    title和content是参数名,也可以通过索引进行装配,如下:

    c:_0="machi"
    c:_1="is a good boy"

    下划线后面的数字指明了参数的索引。

    6.<list>:  当需要注入集合时,可以在<constructor-arg>元素中使用<list>元素来声明列表,如下:

    <constructor-arg>
        <list>
            <value>machi</value>
            <value>is</value>
            <value>a</value>
            <value>good</value>
            <value>boy</value>    
        </list>
    </constructor-arg>

    <list>元素是<constructor-arg>的子元素,这表明一个包含值的列表将会传递到构造器中。其中,<value>元素用来指明列表中的每个元素。

    我们也可以使用<ref>元素代替<value>,实现bean引用列表的装配。

    <ref bean="id名“/>

    7.<set>:  与<list>元素作用相同。

    8.<property>:  <property>元素为属性的Setter方法所提供的功能与<constructor-arg>元素为构造器所提供功能是一样的。它也有ref属性。

    9.p-命名空间:  作为<property>元素的代替方案。为了启用p-命名空间,必须要在XML文件中与其他的命名空间一起对其进行声明:

    xmlns:p="http://www.springframework.org/schema/p

    使用方式如下:

    p:compactDisc-ref="compactDisc"

     示例代码:

    10.<import>:  在XML中,可以使用import元素来拆分XML配置

     

    三.在Java中进行显式装配

    其实就是JavaConfig类,需要和注解一起使用。 

    四.隐式的bean发现机制和自动装配(基于注解的隐式装配)

    1.@Component:  在类上使用@Component注解,这个简单的注解表明该类会作为组件类,并告知spring要为这个类创建bean。

    默认id为将类名的第一个字母变为小写。如果不想使用默认id,可以自定义id,如@Component("自定义id名“)。

    2.@ComponentScan:  组件扫描默认是不启用的。我们需要显示配置一下spring,从而命令它去寻找带有@Component注解的类,并为其创建bean。@ComponentScan注解能够在spring中启用组件扫描。如果没有其他配置的话,@ComponentScan默认会扫描与配置类相同的包,即扫描这个包以及下面的所有子包,查找带有@Component注解的类。

    为了指定不同的基础包,你所需要做的就是在@ComponentScan的value属性中指明包的名称,如@ComponentScan(”包名“)。如果你想要更加清晰地表名你所设置的是基础包,可以通过basePackages属性进行配置,如@ComponentScan(basePackeges=”包名“),如果你想要设置多个基础包,只需要将basePackages属性设置为要扫描包的一个数组即可,如@ComponentScan(basePackages={"包1”,“包2”,.....})。除了将包设置为简单的string类型之外,该注解还提供了另外一种方法,那就是将其指定为包中所包含的类或接口,如@ComponentScan(basePackageClassess={one.class, two.class}),这些类所在的包将会作为组件扫描的基础包。

    3.@Named:  该注解作用与@Component基本相同。

    4.@Autowired:  该注解是用来进行依赖注入的,它会寻找spring容器中适合的bean传递给该方法的参数。@Autowired注解不仅能够用在构造器上,还能用在属性的Setter方法上。实际上该注解可以用在该类的任何方法上.

    不管是构造器、Setter方法还是其他的方法,spring都会尝试满足方法参数上所声明的依赖。

    如果没有匹配的bean,那么在应用上下文创建的时候,spring会抛出一个异常。为了避免异常的出现,你可以将@Autowired的required属性设置为false。将required属性设置为false时,spring会尝试执行自动装配,但是如果没有匹配的bean的话,spring会让这个bean处于未装配的状态。

    如果有多个bean都能满足依赖关系的话,spring将会抛出一个异常,表名没有明确指定要选择哪个bean进行装配。

    5.@Inject:  该注解作用与@Autowired相同。

    6.@Configuration:  创建JavaConfig类的关键在于为其添加@Configuration注解,该注解表名这个类是一个配置类。

    7.@Bean:  要在JavaConfig中声明bean,我们需要编写一个方法,这个方法会创建所需类型的实例,然后给这个方法添加@Bean注解。如下:

    @Bean
    public CompactDisc sgtPeppers(){
        return new SgtPeppers();
    }

    @Bean注解会告诉spring这个方法将会返回一个对象,该对象要注册为spring应用上下文中的bean。

    默认情况下,bean的id与带有@Bean注解的方法名是一样的。在上述例子中,这个bean的id为sgtPeppers。你可以通过name属性指定一个不同的名字。@Bean(name=“id名”)。

    如果你要借助JavaConfig实现注入该怎么做,通过下面这行代码可以实现注入:

    @Bean
    public CompactDisc sgtPeppers(){
        return new SgtPeppers();
    }
    
    @Bean
    public CDPlayer cdPlayer(){
        return new CDPlayer(sgtPeppers());
    }

    第二个bean需要注入第一个bean,所以在构造方法中调用了第一个方法。

    可以看到,通过调用方法来引用bean的方法有点令人困惑。下面是一种更为简单的方法:

    @Bean
    public CDPlayer cdPlayer(CompactDisc compactDisc){
        return new CDPlayer(compactDisc);
    }

    在这里,cdPlayer()方法请求一个CompactDisc作为参数。通过这种方法引用其他bean通常是最佳的选择,因为它不会要求将COmpactDisc声明到同一个配置之中。

    8.@Import:  通过@Import注解将两个类组合在一起。

    9.@ImportResource:  使配置在JavaConfig中的bean和配置在XML中的bean都会被加载到spring容器之中。

    五.最后

     最后想写一点与前面没有关系的东西,不久前在b站看到的了一个视频,题目很新颖,叫“不要做程序员”。up主在视频中并没有说程序员的不好,他只是说在这个编程十分流行的年代,我们不要为了编程而去编程,你要让你做出来的东西带来一些意义,编程只是解决问题的一种工具,而你要成为解决问题的那个人。

  • 相关阅读:
    MySql创建库 Challenge
    未能启用约束。一行或多行中包含违反非空、唯一或外键约束的值的解决办法.
    小总结:用反射机制创建的分配数据分配器
    工厂模式的反思
    单机安装“完整”SharePoint 2010
    作业调度框架 Quartz.NET 2.0 StepByStep(2)
    UI线程同步
    每日见闻(一)
    作业调度框架 Quartz.NET 2.0 StepByStep
    基础算法(ACwing)
  • 原文地址:https://www.cnblogs.com/machi12/p/12268248.html
Copyright © 2011-2022 走看看