Spring提供的三种装配Bean方式
Posted jeremyfa
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring提供的三种装配Bean方式相关的知识,希望对你有一定的参考价值。
在Spring中,对象不需要自己查找或创建与其所关联的其他对象,Spring容器负责把需要相互协作的对象引用赋予各个对象。创建应用对象之间协作关系的行为通常称为装配(wiring),这也是依赖注入(DI)的本质。
Spring提供了三种主要的装配Bean的方式:
- 隐式的bean发现和自动化装配
- 在Java中进行显示配置
- 在XML中进行显示配置
隐式的bean发现和自动化装配
Spring从两个方面来实现自动化装配:
- 组件扫描:Spring会自动发现应用上下文中所创建的bean。
- 自动装配:Spring自动满足bean之间的依赖。
示例代码:
package phone; public interface HWPhone void call();
package phone; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component("p30Phone") @Qualifier("p30") public class P30Phone implements HWPhone @Override public void call() System.out.println("使用 P30 手机呼叫...");
@Component注解表明该类会作为组件类,Spring会为这个类创建bean。“p30Phone"是定义bean的ID。
@Qualifier("p30")创建自定义限定符,防止不仅有一个bean能够匹配结果。
package phone; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component("mete30Phone") @Qualifier("mete30") public class Mete30Phone implements HWPhone @Override public void call() System.out.println("使用 Mete30 手机呼叫...");
package phone; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component("lihua") public class Somebody @Autowired @Qualifier("p30") private HWPhone hwPhone; public void usePhone() hwPhone.call();
@Autowired 自动装配。
@Qualifier("p30")使用限定符。
package phone; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan(basePackages = "phone") public class PhoneConfig
@ComponentScan启动注解扫描,basePackages="phone",指定扫描phone包和phone下的子包;不配置basePhckages则扫描当前配置类的包和子包。
package phone; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Main public static void main(String[] args) AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PhoneConfig.class); Somebody somebody = (Somebody) context.getBean("lihua"); somebody.usePhone();
运行结果:
使用 P30 手机呼叫...
在Java中进行显示配置
想要将第三方库中的组件装配到你的应用中,是没有办法在它的类上添加@Component和@Autowired注解的,这时就不能使用自动化装配了,必须采用显式配置,而显示配置有两种可选方式:使用Java配置或XML配置。JavaConfig是配置代码,它不应包含任何业务逻辑,也不应侵入到业务逻辑代码之中。
在上一节的示例代码中,改为如下代码:
package phone; public interface HWPhone void call();
package phone; public class P30Phone implements HWPhone @Override public void call() System.out.println("使用 P30 手机呼叫...");
package phone; public class Mete30Phone implements HWPhone @Override public void call() System.out.println("使用 Mete30 手机呼叫...");
此处删除了@Component注解,和 @Qualifier注解。
package phone; public class Somebody private HWPhone hwPhone; public Somebody(HWPhone hwPhone) this.hwPhone = hwPhone; public void usePhone() hwPhone.call();
删除了@Autowired注解,以构造器传入HWPhone引用对象,也可以通过set方法设置引用对象。
package phone; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class PhoneConfig @Bean @Qualifier("p30") public P30Phone p30Phone() return new P30Phone(); @Bean @Qualifier("mete30") public Mete30Phone mete30Phone() return new Mete30Phone(); @Bean(name = "lihua") public Somebody somebody() return new Somebody(mete30Phone()); @Bean(name = "xiaoming") public Somebody someone(@Qualifier("p30") HWPhone phone) return new Somebody(phone);
此处删除了@ComponentScan注解,以javaConfig方式配置bean。
“lihua”这个bean是通过调用mete30Phone()得到的,但情况并非完全如此。因为mete30Phone()方法上添加了@Bean注解,Spring将会拦截所有对它的调用,并确保直接返回该方法所创建的bean,而不是每次都对其进行实际的调用。
“xiaoming”这个bean,someone() 方法请求一个HWPhone作为参数。当Spring调用someone()创建bean时,它会自动装配一个HWPhone到配置方法之中。此处的@Qualifier("p30")作为限定符,防止两个bean(p30Phone和mete30Phone)都能够匹配结果。
package phone; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Main public static void main(String[] args) AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PhoneConfig.class); Somebody somebody = (Somebody) context.getBean("lihua"); somebody.usePhone(); Somebody someone = (Somebody) context.getBean("xiaoming"); someone.usePhone();
运行结果:
使用 Mete30 手机呼叫...
使用 P30 手机呼叫...
在XML中进行显示配置
在JavaConfig中所需要的只是@Configuration,但在使用XML时,需要在配置文件的顶部声明多个XML模式(XSD)文件,这些文件定义了配置Spring的XML元素。
创建一个application.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-4.3.xsd"> <bean id="p30Phone" class="phone.P30Phone"/> <bean id="mete30Phone" class="phone.Mete30Phone"/> <bean id="lihua" class="phone.Somebody"> <constructor-arg ref="p30Phone"/> </bean> <bean id="xiaoming" class="phone.Somebody"> <constructor-arg ref="mete30Phone"/> </bean> </beans>
基于上一节的示例,不用PhoneConfig配置类,并使用ClassPathXmlApplicationContext创建Spring容器,Main方法如下:
package phone; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main public static void main(String[] args) ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("phone/application.xml"); Somebody somebody = (Somebody) context.getBean("lihua"); somebody.usePhone(); Somebody someone = (Somebody) context.getBean("xiaoming"); someone.usePhone();
运行结果:
使用 P30 手机呼叫...
使用 Mete30 手机呼叫...
导入和混合配置
在JavaConfig中引用XML
package phone; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class PhoneConfig @Bean public P30Phone p30Phone() return new P30Phone(); @Bean public Mete30Phone mete30Phone() return new Mete30Phone();
此处只配置Phone的两个Bean。
<?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-4.3.xsd">
<bean id="lihua" class="phone.Somebody">
<constructor-arg ref="p30Phone"/>
</bean>
<bean id="xiaoming" class="phone.Somebody">
<constructor-arg ref="mete30Phone"/>
</bean>
</beans>
XML配置文件配置了"lihua"和"xiaoming"两个Somebody的bean。
package phone; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.ImportResource; @Configuration @Import(PhoneConfig.class) @ImportResource("classpath:phone/application.xml") public class SomebodyConfig
配置通过@Import引用Phone的配置,以及通过@ImportResource引用XML的配置
package phone; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Main public static void main(String[] args) AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SomebodyConfig.class); Somebody somebody = (Somebody) context.getBean("lihua"); somebody.usePhone(); Somebody someone = (Somebody) context.getBean("xiaoming"); someone.usePhone();
运行结果:
使用 P30 手机呼叫...
使用 Mete30 手机呼叫...
参考《Spring实战(第4版)》
以上是关于Spring提供的三种装配Bean方式的主要内容,如果未能解决你的问题,请参考以下文章