spring提供了三种bean的装配机制java
- 1、在XML中进行显示配置;
- 2、在Java中进行显示配置;
- 3、隐式的bean发现机制和自动装配
1、自动化装配beanspring
CD播放器依赖于CD,只有将CD插入(注入)到CD播放器,CD播放器才能放出音乐。安全
一、spring从两个角度来实现自动化装配ide
- 组件扫描(component scanning):spring会自动发现应用上下文中所建立的bean
- 自动装配(autowiring):spring自动知足bean之间的依赖
二、@Component 注解代表该类会做为组件类,并告知spring要为这个类建立bean;组件扫描默认不启用,需组合@ComponentScan 注解使用。ui
三、@ComponentScan 启用组件扫描,若是没有其余配置,@ComponentScan默认会扫描与配置类相同的包。例,CDPlayerConfig类位于soundsystem包中,所以spring将会扫描这个包及这个包下的全部子包,查找带有@Compnent注解的类,这样就能发现CompactDisc,而且会在spring中自动为其建立一个bean;在xml中的使用:<context:componet-scan base-package="com.spring.soundsystem">。component
四、为组件扫描的bean命名:spring应用上下文中全部的bean都会给定一个ID,@Component注解默认为ID为类名首字母小写,可自定义命名@Component("newName");也可使用Java依赖注入规范中提供的@Named注解为bean设置ID,如:@Named("newName")。大多数场景中二者可相互替换,但推荐使用@Component,由于@Named注解语意不明。xml
五、设置组件扫描的基础包对象
@componetScan会以配置类所在的包做为基础包(base package)来扫描组件,若是咱们将配置类放在单独的包中,使其与其余的代码区分开来,就须要在@Component的value属性中指明包的名称:blog
@Configuration @ComponentScan("com.spring.soundsystem") public class CDPlayConfig{ }若是想更加清晰的代表设置的基础包,能够经过basePackage属性进行配置:接口
@Configuration @ComponentScan(basePackages="com.spring.soundsystem") //@ComponentScan(basePackages{"com.spring.soundsystem","com.spring.video"}) public class CDPlayConfig{ }以上方法基础包为String类型,这种方法是类型不安全的(not type-safe),@Componet还提供另一种方法,那就是将其指定为包中所包含的类或者接口
@Configuration @compnentScan(basePackageClasses={CDPlayer,class,Video.claass}) public class CDPlayerConfig{ }六、经过为bean添加注解实现自动装配
@autowired注解可用在类的任何方法上,不只可以用在构造器上,还能用在属性的Setter方法上;若是没有匹配的bean,那么在应用上下文建立的时候,spring会抛出一个异常,为避免异常,可将@autowired的required属性设置为false,即:@autowired(required=false);将required属性设置为false时,spring会尝试执行自动装配,若是没有匹配的bean,sping将会让这个bean处于为装配的状态。同时,须要先在代码中进行null检查,不然会出现NullPointerException。若是有多个bean都能知足依赖关系,spring会抛出一个异常,代表没有明确指定选择哪一个bean进行自动装配。可以使用Java依赖注入规范的@Inject注解替换@Autowired。
2、经过Java代码装配bean(JavaConfig)
一、建立JavaConfig类的关键在于为其添加@Configruration注解,@Configuration注解代表这个类是一个配置类,该类应包含在spring应用上下文中如何建立bean的细节。
二、声明简单的bean
// @Bean注解会告诉spring这个方法返回一个对象,该对象要注册为spring应用上下文的bean // 默认状况下,bean的id与带有@Bean注解的方法名是同样的 // 若是想设置一个不一样的名字,能够重命名该方法,也能够经过name属性指定一个不一样的名字,@Bean(name = "lonelyHeartsClubBand") @Bean public CompactDisc sgtPeppers(){ return new SgtPeppers(); }三、借助JavaConfig实现注入
在JavaConfig中装配bean的最简单方式就是引用建立的bean的方法。
// 看起来CompactDisc是经过调用sgtPeppers()获得的,但状况并不是彻底如此。由于sgtPeppers()方法上添加了@Bean注解,spring将会拦截全部对它的调用,并确保直接返回该方法所建立的bean,而不是每次都对其进行实际的调用 @Bean public CDPlayer cdPlayer(){ return new CDPlayer(sgtPeppers()) ; } // 另外一种理解起来更为简单的方式,CDPlayer的构造器实现DI @Bean pubic CDPlayer cdPlayer(CompactDisc compactDisc){ return new CDPlayer(compactDisc); } // Setter方法注入 public CDPlayer cdPlayer(CompactDisc compactDisc){ CDPlayer cdPlayer = new CDPlayer(compactDisc); cdPlayer.setCompactDisc(compactDisc); return cdPlayer; }
3、经过XML装配Bean
一、建立一个XML文件,必须以<beans>元素为根,最为简单的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 http://www.springframework.org/schema/context"> </beans>二、声明一个简单的<bean>
// 默认的ID"soundsystem.SgtPeppers#0","#0"是一个计数形式 <bean class="soundsystem.SgePeppers" /> // 为bena设置一个id <bean id="compactDisc" class="soundsystem.SgePeppers" />当spring发现这个<bean>元素时,它将会调用SgtPeppers的默认构造器来建立bean。须要注意的是,在这个简单的<bean>声明中,咱们将bean的类型以字符串的形式设置在了class属性中。谁能保证设置给class属性的值是真正的类呢?Spring的XML配置并不能从编译器的类型检查中受益。即使它所引用的是实际的类型,若是你重命名了类,会发生什么呢?
三、借助构造器注入初始化bean
具体到构造器注入,有两种基本的配置方案可供选择:
· <constructor-arg>元素
· 使用spring 3.0所引用的c-命名空间
3.一、构造器注入bean引用
<bean id ="cdPlayer" class="soundsystem.CDPlayer"> <constructor-arg ref="compactDisc" /> </bean>当spring遇到<bean>元素时,他会建立一个CDPlayer实例。<constructor-arg>元素会告知spring要将一个ID为compactDisc的bean引用传递到CDPlayer的构造器中。
c-命名空间是在spring3.0中引入的,他是在XML中更为简洁第描述构造器参数的方式,要使用它必需要在XML的顶部声明其模式。
<bean id="cdPlayer" class="soundsystem.CDPlayer" c:cd-ref="compactDisc">四、将字面变量注入到构造器中
假设要建立CompactDisc的一个新实现
<bean id="compactDIs" class="soundsystem.BlankDisc"> <constructor-arg value="Sgt. Pepper's Loney Hearts Club Band" /> <constructor-arg value="The Beatles" /> </bean>这里没有使用“ref”属性来引用其余的bean,而是使用了value属性,经过该属性代表给定的值要以字面量的形式注入待构造器中(“ref”,引用传递,“value”,值传递)。
五、设置属性
如何选择构造器注入仍是属性注入?对于强依赖使用构造器注入,二队可选性的依赖使用属性注入。
<bean id="cdPlayer" class="soundsystem.CDPlayer"> <property name="compactDisc" ref="compactDisc" /> </bean><property>元素为属性的Setter方法所提供的功能与<constructor-arg>元素为构造器所提供的功能是同样的。在本例中,它引用了ID为compactDisc的bean(经过ref属性),并将其注入到compactDisc属性中(经过setCompactDisc()方法)。
spring为<constructoer-arg>元素提供了c-命名空间做为替代方案,与之相似,sping提供了更加简洁的p-命名空间,做为<property>元素的替代方案。
使用p-命名空间须要进行声明:
咱们可使用p-命名空间,按照如下的方式装配compactDisc属性
<bean id="cdPlayer" class="soundsystem.CDPlayer" p:compactDisc-ref="compactDisc">"p:"前缀代表咱们设置的是一个属性,属性名称以“-ref”提示spring要进行装备的是引用而不是字面量。
将字面量注入到属性中