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主在视频中并没有说程序员的不好,他只是说在这个编程十分流行的年代,我们不要为了编程而去编程,你要让你做出来的东西带来一些意义,编程只是解决问题的一种工具,而你要成为解决问题的那个人。

原文地址:https://www.cnblogs.com/machi12/p/12268248.html