装配Bean
Spring装配Bean的三种方式
- 1.在XML中进行显示配置
- 2.在Java中进行显示配置
- 3.隐式的Bean发现和自动装配
尽可能地的使用自动配置的机制。显示的配置越少越好,当你必须要显示配置Bean的时候(比如:有些源码不是由你来维护的,而当你需要为这些代码配置的时候),推荐使用类型安全(因为在Java配置中可以利用编译器检查)并且比XML更加强大的JavaConfig。最后,只有当你想要使用便利的XML命名空间,并且在JavaConfig中没有同样的实现时,才应该使用XML。
实现类:
public class App {
public void hello() {
System.out.println( "Hello World!");
}
}
public class AppUser {
private App app;
public AppUser(App app){
this.app = app;
}
public Integer TestApp(){
System.out.println(app);
return 1;
}
}
xml显示配置方式:
<bean id="appTest" class="chendongdong.spring.test.bean.Test1.App">
</bean>
<bean id="appUser" class="chendongdong.spring.test.bean.Test1.AppUser">
<constructor-arg ref="appTest"></constructor-arg>
</bean>
使用Xml方式,测试类:
ClassPathXmlApplicationContext context1 = new ClassPathXmlApplicationContext("spring.xml");
AppUser bean1 = context1.getBean(AppUser.class);
bean1.TestApp();
Java显示配置:
@Configuration
public class CompactConfig {
@Bean
public App app(){
return new App();
}
@Bean
public AppUser appUser(){
return new AppUser(null);
}
}
使用注解,测试,如下:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CompactConfig.class);
appUser bean = (appUser)context.getBean("appUser");
bean.TestApp();
自动发现和装配:
使用Bean自动发现和装配的方式,则需要在Bean类上用@Component注解进行标识。通过@CompentScan(basePackages="")进行组件扫描。使用@AutoWired注解进行自动装配。
@Component
public class AppUser {
private App app;
public AppUser(App app){
this.app = app;
}
public Integer TestApp(){
System.out.println(app);
return 1;
}
}
@Component
public class App {
public void hello() {
System.out.println( "Hello World!");
}
}
@ComponentScan(basePackageClasses = {AppUser.class, App.class})
@ComponentScan(basePackages = "chendongdong.spring.test.bean")
@Configuration
public class CompactConfig {
}
测试,如下:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CompactConfig.class);
appUser bean = (appUser)context.getBean("appUser");
bean.TestApp();
总结:
- 创建应用对象之间的协作关系行为通常称为装配,这也是依赖注入(DI)的本质。
- @ComponentScan默认会扫描与配置类相同的包。组件扫描默认是不启动的。@ComponentScan除了basePackages属性,还有basePackageClasses属性。
- @Bean 注解会告诉Spring这个方法将会返回一个对象。默认情况下,bean的ID与带有@Bean注解的方法名一样。
- @component 默认是使用类名首字母小写作为Bean的id。当然也可以用其属性自定义指定。
属性注入
构函数造注入
<bean id="appTest" class="chendongdong.spring.test.bean.Test1.App">
<constructor-arg name="name" value="app"/>
</bean>
<bean id="appUser" class="chendongdong.spring.test.bean.Test1.AppUser">
<constructor-arg ref="appTest"></constructor-arg>
</bean>
更多的配置方式:
<bean id="appUser" class="chendongdong.spring.test.bean.Test1.AppUser">
//其他对象
<constructor-arg ref="appTest"></constructor-arg>
//普通参数 通过默认的Index顺序,否则顺序不能错
<constructor-arg index="1" value="66.6"/>
<constructor-arg index="0" value="粉色"/>
//list集合
<constructor-arg>
<list>
<value>蓝色</value>
<value>红色</value>
<value>黑色</value>
</list>
</constructor-arg>
//set集合
<constructor-arg name="earPhones">
<set>
<ref bean="earPhone1"/>
<ref bean="earPhone2"/>
<ref bean="earPhone3"/>
<ref bean="earPhone4"/>
<ref bean="earPhone5"/>
</set>
</constructor-arg></bean>
<!--通过c-index命名空间-->
<bean id="appTest" class="chendongdong.spring.test.bean.Test1.AppUser"
c:_0="蓝色" c:_1="88.8"/>
<!--通过c-name命名空间-->
<bean id="appTest" class="chendongdong.spring.test.bean.Test1.AppUser"
c:color="绿色" c:price="90.8"/>
Set注入
<property name="earPhones"> 标签替换 <constructor-arg/>
<bean id="appUser" class="chendongdong.spring.test.bean.Test1.AppUser">
<property name="name" value="华为手机"/>
//集合引用类型注入
<property name="earPhones">
<list>
<ref bean="earPhone1"/>
<ref bean="earPhone2"/>
</list>
</property></bean>
注意:
-
可以使用 或者 标签可以将null注入。
-
p 和 c-arg 区别: 元素为属性的setter方法所提供的功能与 元素为构造器所提供的功能时一样的。Spring为 元素提供了c-命名空间作为替代方案,与之类似,Spring提供了更加简洁的p-命名空间,作为 元素的替代方案。
导入和混合配置
实际开发中,也许时Xml显示配置和JavaConfig显示配置都存在,并且需要XML与XML相互引用,甚至的XML和JavaConfig交叉引用。所以,下面我们来看一下如何进行相互使用:
XML配置文件相互引用
app配置文件
<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 id="huaweiBattery" class="chendongdong.spring.test.bean.Test1.App">
<property name="brand" value="Huawei"/>
<property name="name" value="华为荣耀手机"/>
</bean>
</beans>
AppUser配置文件
<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">
<import resource="app.xml"/>
<bean id="huaweiBattery" class="chendongdong.spring.test.bean.Test1.AppUser">
<property name="brand" value="Huawei"/>
<property name="name" value="华为荣耀手机"/>
</bean>
</beans>
实际开发中,不可能将所有的配置信息写到一个XML文件中,所以存在相互引用,上述代码可以测试出,在xml文件
如何引用另外一个xml文件。一般,可以单独创建一个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">
<import resource="App.xml"/>
<import resource="AppUser.xml"/>
</beans>
Java配置类相互引用
在XML文件中是使用<import resource = ‘aa.xml’ 而在JavaConfig配置类中导入是使用@import({Config.class})注解。通过导入的配置类的class类即可。
@Configuration
@Import({AppUser.class})
//@ImportResource("classpath:spring.xml")
public class AppUserConfig {
@Bean
public AppUser appUser(){
return new AppUser();
}
}
@Configuration
public class AppConfig {
@Bean
public App app(){
return new App();
}
}
Java配置类中引用Xml配置文件
@ImportResource
@Configuration
@ImportResource("classpath:spring.xml")
public class AppUserConfig {
@Bean
public AppUser appUser(){
return new AppUser();
}
}
@Configuration
public class AppConfig {
@Bean
public App app(){
return new App();
}
}
Xml配置文件中引用Java配置类
<bean class="chendongdong.spring.test.bean.Test2.CompactConfig"/>
<context:component-scan base-package="chendongdong.spring.test.bean.Test2.CompactConfig"/>
使用标签将配置文件导入,则可以在ref中引用到,但是此时测试还是会报错误,需要使用 配合使用