Spring实战笔记——装配Bean

xiaoxiao2021-02-28  107

上一章主要讲述了Spring的主要设计思路。接下来的章节将讲解Spring各种设计思路的具体实现。本章和下一章重点讲解Bean的装配方式,本章将重点介绍Bean的基本装配方法。

本章内容:

声明bean构造器注入和Setter 装配bean 控制bean的创建和销毁

一个软件的作用是实现某种功能,当然功能也有简单和复杂之分。你可以将一个具有复杂功能的应用程序看作一个功能来实现——写一个很大很大很大的源代码,也可以将这个具有复杂功能的程序进行拆分,然后由一些简单的程序(组件)通过协作的方式来实现复杂的功能。而软件的模块化设计几乎是现代所有程序设计都遵循的规则。 Spring也是遵循这个思路的。Spring已经完成了很多底层的功能,程序员只需要按照功能的需求写出相应的应用组件,再通过容器把需要相互协作的组件进行管理。在java中,一个对象可以看作是一个组件,Spring创建对象之间协作关系的行为称为装配,者也是DI的本质

1, Spring配置bean的方案

spring有三种基本的装配bean机制:

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

可以只采用一种方式(自己喜欢的)来装配bean,也可以freestyle,将三种装配方式混合使用。

Spring实战作者推荐的装配策略:尽可能使用自动配置的机制,这样显示的配置最少。当必须显示配置bean的时候,优先使用类型安全并且比XML更加强大的JavaConfig。最后当想要使用便利的XML命名空间,并且在JavaConfig中没有同样的实现时,应该使用XML。

1.1,自动化装配bean

Spring从两个角度来实现自动化装配:

组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean。自动装配(autowiring):Spring自动满足bean之间的依赖关系。

首先创建一个可以被发现的bean。 以CD机为例(参考书本):

package com.example.chr1s; public interface CompactDisc { void play(); }

这里定义了一个接口,CD可以存放音乐,所有的CD都是能播放的,所以在接口里定义了一个play()方法,但是CD里面存储的具体是什么则应该由实现该接口的类来表示。

接着创建一个实现这个接口的类

package com.example.chr1s; import org.springframework.stereotype.Component; @Component public class SgtPeppers implements CompactDisc { private String title "Sgt. Pepper's Lonely Hearts Club Band"; private String artist = "The Beatles"; @Override public void play() { System.out.println("Playing " + title + " by " + artist); } }

@Component注解表明该类会作为组件类,并且告知Spring要为这个类创建bean。

组件扫描默认是关闭的,需要显示配置Spring,从而命令它去寻找带有@Component注解的类。

package com.example.config; import org.springframework.context.annotation.componentScan; import org.springframe.context.annotation.Con; @Configuration @ComponentScan("com.example.chr1s") public class CDPlayerConfig { }

@Configuration注解表明CDplayerConfig 是一个Java配置类,@ComponentScan能够在Spring中启动组件扫描。 @ComponentScan注解如果没有参数,则默认在当前包中扫描bean。给定参数后,在参数所标定的位置进行扫描。

测试组件扫描能够发现CompactDisc

package com.example.chr1s; import com.example.config.CDPlayerConfig; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static org.junit.Assert.assertNotNull; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=CDPlayerConfig.class) public class CDPlayerTest { @Autowired private CompactDisc cd; @Test public void cdShouldNotBeNull() { assertNotNull(cd); } }

单元测试以后再说,这里重点说明Spring相关的东西。SpringJUnit4ClassRunner可以在测试开始的时候自动创建Spring的应用上下文,@ContextConfiguretion会告诉它需要的配置文件。@Autowiring注解表示自动装配bean。

关于bean的一些额外配置

为组件扫描的bean命名:@Component(“beanID”)使用Java注入规范的@Named注解为bean设置ID:@Named(“beanID”)为自动扫描设置多个基础包:@ComponentScan(basePackages={“package1”, “package2”, “package3”})

如果要求自动扫描实现类型安全:@ComponentScan(basePackageClasses={interface1.class, interface2.class}),对应的类所在的包将作为扫描组件的基础包

以上的代码实现了bean的最基本的装配,这些bean彼此之间还没有依赖关系。在实际的程序设计中,bean之间是相互依赖的,需要将扫描得到的bean和它们的依赖装配到一起。

自动装配是为了让Spring自动满足bean依赖的一种方法。

package com.example.chr1s; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class CDPlayer implements CompactDisc { private CompactDisc cd; @Autowired public CDPlayer(CompactDisc cd) { this.cd = cd; } public void play() { cd.play(); } }

一个CDPlayer能正常播放需要有插入CD,也就是说CDPlayer是依赖CompactDisc的。在上面的代码中,@Autowried用于构造器上。@Autowried注解还能用在属性的Setter方法上。在Spring初始化bean之后,它会尽可能去满足bean的依赖。

Spring装配bean的异常处理方式:

假如有且只有一个bean匹配依赖需求,那么这个bean就会被装配进来。如果没有匹配的bean,Spring在应用上下文创建的时候会抛出一个异常。如果将@autowried的require属性设置成false,会抑制这个异常,但是在接下来的代码中,如果对bean的引用没有进行null检查的话,这个未装配状态的属性则由可能出现NullPointerException。如果多个bean都能满足依赖关系的话,Spring也会抛出异常。

验证自动装配:

package com.example.chr1s; import com.example.config.CDPlayerConfig; import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.StandardOutputStreamLog; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=CDPlayerConfig.class) public class CDPlayerTest { @Rule public final StandardOutputStreamLog log = new StandardOutputStreamLog(); @Autowired private CompactDisc cd; @Autowired private CDPlayer player; @Test public void cdShouldNotBeNull() { assertNotNull(cd); } @Test public void play() { player.play(); assertEquals("Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles\r\n", log.getLog()); } }

通过Java代码显示装配bean

自动化装配不是万能的,比如自动化装配就无法将第三方库中的组件装配到自己的应用中。显示的装配方式有两种:

基于Java基于XML

基于Java的显示装配

@Bean注解会告诉Spring接下来编写的方法将返回一个对象,该对象会注册为Spring应用上下文中的bean。默认情况下,bean的ID与带有@Bean注解的方法名是一样的,也可以通过name属性进行修改:

@Bean(name="beanID") public CompactDisc sgtPeppers() { return new SgtPeppers(); }

通过Java代码实现DI-构造器注入

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

通过Java代码实现DI-Setter方法注入

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

通过XML装配Bean

XML设置有几个重要的节点

<beans>节点是所有bean的根节点<bean>节点对应Spring中的一个bean,它有几个重要的属性:1,id属性,对应JavaConfig中的name属性;class属性表明bean所属的类<constructor-arg>确定bean的构造器参数。它是<bean>节点的子节点,也有几个重要的属性:1,value属性,表征字面值常量参数;2,ref属性,表征引用类型参数。constructor-arg节点还有一些子节点,如list, map等,用于定义集合来作为构造器参数。这些属性是实现构造器注入的基础。<property>节点用于实现Setter注入。 与<constructor-arg>类似,它也有几个重要属性:1,name,表征引用的变量;2,value表征具体的值;list,map等子节点用法与第三点中的一样。

XML的配置方法的示例代码本文不再描述

混合配置

1,在JavaConfig中导入XML配置 在JavaConfig中通过@Import注解导入其它JavaConfig类中的配置,通过@ImportResource注解导入XML配置

2,在XML中导入JavaConfig 在XML中使用<import>元素导入XML配置文件 ,如<import resource="spring-config.xml">,通过在<bean>中引入JavaConfig名称能导入JavaConfig文件, 如<bean class="com.example.config.CDPlayerConfig">。

转载请注明原文地址: https://www.6miu.com/read-30973.html

最新回复(0)