控制bean的创建和销毁
创建应用对象之间关联关系的传统方法(通过构造器或者查找)通常会导致结构复杂的代码,这些代码很难被复用也很难进行单元测试。如果情况不严重的话,这些对象所做的事情只是超出了它应该做的范围;而最坏的情况则是,这些对象彼此之间高度耦合,难以复用和测试。
Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系。但是,作为开发人员,你需要告诉Spring要创建哪些bean并且如何将其装配在一起。当描述bean如何进行装配时,Spring具有非常大的灵活性,它提供了三种主要的装配机制:
Spring的配置风格是可以互相搭配的,所以你可以选择使用XML装配一些bean,使用Spring基于Java的配置(JavaConfig)来装配另一些bean,而将剩余的bean让Spring去自动发现。
Spring从两个角度来实现自动化装配:
组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean。
自动装配(autowiring):Spring自动满足bean之间的依赖。
使用了@Component注解。这个简单的注解表明该类会作为组件类,并告知Spring要为这个类创建bean。启用的。我们还需要显式配置一下Spring,从而命令它去寻找带有@Component注解的类,并为其创建bean;@ComponentScan注解启用了组件扫描。使用XML来启用组件扫描的话,那么可以使用Spring context命名空间的
如果没有其他配置的话,@ComponentScan默认会扫描与配置类相同的包。以及这个包下的所有子包
Spring应用上下文中所有的bean都会给定一个ID。如果想为这个bean设置不同的ID,你所要做的就是将期望的ID作为值传递给@Component注解。如:@Component("xxxxxx")
还有另外一种为bean命名的方式,这种方式不使用@Component注解,而是使用Java依赖注入规范(Java Dependency Injection)中所提供的@Named注解来为bean设置ID:
还有另外一种为bean命名的方式,这种方式不使用@Component注解,而是使用Java依赖注入规范(Java Dependency Injection)中所提供的@Named注解来为bean设置ID:(jdk1.8没有找到这个注解)
没有为@ComponentScan设置任何属性。这意味着,按照默认规则,它会以配置类所在的包作为基础包(basepackage)来扫描组件。但是,如果你想扫描不同的包,那该怎么办呢?或者,如果你想扫描多个基础包,那又该怎么办呢?指定不同的基础包,你所需要做的就是在@ComponentScan的value属性中指明包的名称:@ComponentScan("包名");
清晰地表明你所设置的是基础包,那么你可以通过basePackages属性进行配置:@ComponentScan(basePackages="");
将basePackages属性设置为要扫描包的一个数组,可以扫描多个包;除了将包设置为简单的String类型之外,@ComponentScan还提供了外一种方法,将指定为包中所包含的类或接口;@ComponentScan(basePackageClasses= {})
简单来说,自动装配就是让Spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在Spring应用上下文中寻找匹配某个bean需求的其他bean。为了声明要进行自动装配,我们可以借助Spring的@Autowired注解。
如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。为了避免异常的出现,你可以将@Autowired的
required属性设置为false。
如果有多个bean都能满足依赖关系的话,Spring将会抛出一个异常,表明没有明确指定要选择哪个bean进行自动装配。
@Autowired是Spring特有的注解。如果你不愿意在代码中到处使用Spring的特定注解来完成自动装配任务的话,那么你可以考虑将其替换为@Inject:
尽管在很多场景下通过组件扫描和自动装配实现Spring的自动化配置是更为推荐的方式,但有时候自动化配置的方案行不通,因此需要明确配置Spring。比如说,你想要将第三方库中的组件装配到你的应用中,在这种情况下,是没有办法在它的类上添加@Component和@Autowired注解的,因此就不能使用自动化装配的方案了。在进行显式配置的时候,有两种可选方案:Java和XML。
创建JavaConfig类的关键在于为其添加@Configuration注解,@Configuration注解表明这个类是一个配置类,该类应该包含在Spring应用上下文中如何创建bean的细节。
要在JavaConfig中声明bean,我们需要编写一个方法,这个方法会创建所需类型的实例,然后给这个方法添加@Bean注解
如果你想为其设置成一个不同的名字的话,那么可以重命名该方法,也可以通过name属性指定一个不同的名字:
在使用XML为Spring装配bean之前,你需要创建一个新的配置规范。在使用JavaConfig的时候,这意味着要创建一个带有@Configuration注解的类,而在XML配置中,这意味着要创建一个XML文件,并且要以
在Spring Tool Suite的菜单中,选择File>New>Spring Bean Configuration File,能够创建SpringXML配置文件,并且可以选择可用的配置命名空间。
要在基于XML的Spring配置中声明一个bean,我们要使用spring-beans模式中的另外一个元素:
JavaConfig中的@Bean注解。
借助构造器注入初始化bean;
使用Spring 3.0所引入的c-命名空间
使用参数在整个参数列表中的位置信息:
该选择构造器注入还是属性注入呢?作为一个通用的规则,我倾向于对强依赖使用构造器注入,而对可选性的依赖使用属性注入。
Spring为
作为
与c-命名空间一样,装配bean引用与装配字面量的唯一区别在于是否带有“-ref”后缀。如果没有“-ref”后缀的话,所装配的就是字面量。
util-命名空间所提供的功能之一就是
Spring util-命名空间中的元素
util:list 创建一个 java.util.List 类型的 bean ,其中包含值或引用
util:map 创建一个 java.util.Map 类型的 bean ,其中包含值或引用
util:properties 创建一个 java.util.Properties 类型的 bean
util:property-path 引用一个 bean 的属性(或内嵌属性),并将其暴露为 bean
util:set 创建一个 java.util.Set 类型的 bean ,其中包含值或引用
在典型的Spring应用中,我们可能会同时使用自动化和显式配置。即便你更喜欢通过JavaConfig实现显式配置,但有的时候XML却是最佳的方案。幸好在Spring中,这些配置方案都不是互斥的。你尽可以将JavaConfig的组件扫描和自动装配和/或XML配置混合在一起。关于混合配置,第一件需要了解的事情就是在自动装配时,它并不在意要装配的bean来自哪里。自动装配的时候会考虑到Spring容器中所有的bean,不管它是在JavaConfig或XML中声明的还是通过组件扫描获取到的。
5.1在JavaConfig中引用XML配置
@Import注解导入;可以将配置引入;采用一个更好的办法,创建一个更高级别的SoundSystemConfig,在这个类中使用@Import将两个配置类组合在一起:
置在了XML之中,我们该如何让Spring同时加载它和其他基于Java的配置呢?@ImportResource注解可以导入xml
5.2在XML配置中引用JavaConfig
在XML中,我们可以使用import元素来拆分XML配置。
已经熟知的元素能够用来将Java配置导入到XML配置中:
创建一个更高层次的配置文件,这个文件不声明任何的bean,只是负责将两个或更多的配置组合起来。