经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
Spring提供的三种装配Bean方式
来源:cnblogs  作者:JeremyFa  时间:2019/6/20 9:00:23  对本文有异议

在Spring中,对象不需要自己查找或创建与其所关联的其他对象,Spring容器负责把需要相互协作的对象引用赋予各个对象。创建应用对象之间协作关系的行为通常称为装配(wiring),这也是依赖注入(DI)的本质。

Spring提供了三种主要的装配Bean的方式:

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

 

隐式的bean发现和自动化装配

 

 Spring从两个方面来实现自动化装配:

  • 组件扫描:Spring会自动发现应用上下文中所创建的bean。
  • 自动装配:Spring自动满足bean之间的依赖。

示例代码:

  1. package phone;
  2. public interface HWPhone {
  3. void call();
  4. }

 

  1. package phone;
  2. import org.springframework.beans.factory.annotation.Qualifier;
  3. import org.springframework.stereotype.Component;
  4. @Component("p30Phone")
  5. @Qualifier("p30")
  6. public class P30Phone implements HWPhone {
  7. @Override
  8. public void call() {
  9. System.out.println("使用 P30 手机呼叫...");
  10. }
  11. }

@Component注解表明该类会作为组件类,Spring会为这个类创建bean。“p30Phone"是定义bean的ID。

@Qualifier("p30")创建自定义限定符,防止不仅有一个bean能够匹配结果。

 

  1. package phone;
  2. import org.springframework.beans.factory.annotation.Qualifier;
  3. import org.springframework.stereotype.Component;
  4. @Component("mete30Phone")
  5. @Qualifier("mete30")
  6. public class Mete30Phone implements HWPhone {
  7. @Override
  8. public void call() {
  9. System.out.println("使用 Mete30 手机呼叫...");
  10. }
  11. }

 

  1. package phone;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.beans.factory.annotation.Qualifier;
  4. import org.springframework.stereotype.Component;
  5. @Component("lihua")
  6. public class Somebody {
  7. @Autowired
  8. @Qualifier("p30")
  9. private HWPhone hwPhone;
  10. public void usePhone() {
  11. hwPhone.call();
  12. }
  13. }
  1. @Autowired 自动装配。
  1. @Qualifier("p30")使用限定符。

 

  1. package phone;
  2. import org.springframework.context.annotation.ComponentScan;
  3. import org.springframework.context.annotation.Configuration;
  4. @Configuration
  5. @ComponentScan(basePackages = {"phone"})
  6. public class PhoneConfig {
  7. }
  1. @ComponentScan启动注解扫描,basePackages={"phone"},指定扫描phone包和phone下的子包;不配置basePhckages则扫描当前配置类的包和子包。

 

  1. package phone;
  2. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  3. public class Main {
  4. public static void main(String[] args) {
  5. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PhoneConfig.class);
  6. Somebody somebody = (Somebody) context.getBean("lihua");
  7. somebody.usePhone();
  8. }
  9. }

运行结果:

  1. 使用 P30 手机呼叫...

 

在Java中进行显示配置

 想要将第三方库中的组件装配到你的应用中,是没有办法在它的类上添加@Component和@Autowired注解的,这时就不能使用自动化装配了,必须采用显式配置,而显示配置有两种可选方式:使用Java配置或XML配置。JavaConfig是配置代码,它不应包含任何业务逻辑,也不应侵入到业务逻辑代码之中。

在上一节的示例代码中,改为如下代码:

  1. package phone;
  2. public interface HWPhone {
  3. void call();
  4. }

 

  1. package phone;
  2. public class P30Phone implements HWPhone {
  3. @Override
  4. public void call() {
  5. System.out.println("使用 P30 手机呼叫...");
  6. }
  7. }

 

  1. package phone;
  2. public class Mete30Phone implements HWPhone {
  3. @Override
  4. public void call() {
  5. System.out.println("使用 Mete30 手机呼叫...");
  6. }
  7. }

此处删除了@Component注解,和 @Qualifier注解。

  1. package phone;
  2. public class Somebody {
  3. private HWPhone hwPhone;
  4. public Somebody(HWPhone hwPhone) {
  5. this.hwPhone = hwPhone;
  6. }
  7. public void usePhone() {
  8. hwPhone.call();
  9. }
  10. }

删除了@Autowired注解,以构造器传入HWPhone引用对象,也可以通过set方法设置引用对象。

  1. package phone;
  2. import org.springframework.beans.factory.annotation.Qualifier;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. @Configuration
  6. public class PhoneConfig {
  7. @Bean
  8. @Qualifier("p30")
  9. public P30Phone p30Phone() {
  10. return new P30Phone();
  11. }
  12. @Bean
  13. @Qualifier("mete30")
  14. public Mete30Phone mete30Phone() {
  15. return new Mete30Phone();
  16. }
  17. @Bean(name = "lihua")
  18. public Somebody somebody() {
  19. return new Somebody(mete30Phone());
  20. }
  21. @Bean(name = "xiaoming")
  22. public Somebody someone(@Qualifier("p30") HWPhone phone) {
  23. return new Somebody(phone);
  24. }
  25. }

此处删除了@ComponentScan注解,以javaConfig方式配置bean。

“lihua”这个bean是通过调用mete30Phone()得到的,但情况并非完全如此。因为mete30Phone()方法上添加了@Bean注解,Spring将会拦截所有对它的调用,并确保直接返回该方法所创建的bean,而不是每次都对其进行实际的调用。

“xiaoming”这个bean,someone() 方法请求一个HWPhone作为参数。当Spring调用someone()创建bean时,它会自动装配一个HWPhone到配置方法之中。此处的@Qualifier("p30")作为限定符,防止两个bean(p30Phone和mete30Phone)都能够匹配结果。

  1. package phone;
  2. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  3. public class Main {
  4. public static void main(String[] args) {
  5. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PhoneConfig.class);
  6. Somebody somebody = (Somebody) context.getBean("lihua");
  7. somebody.usePhone();
  8. Somebody someone = (Somebody) context.getBean("xiaoming");
  9. someone.usePhone();
  10. }
  11. }

运行结果:

  1. 使用 Mete30 手机呼叫...
  2. 使用 P30 手机呼叫...

 

在XML中进行显示配置

 在JavaConfig中所需要的只是@Configuration,但在使用XML时,需要在配置文件的顶部声明多个XML模式(XSD)文件,这些文件定义了配置Spring的XML元素。

创建一个application.xml配置文件:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
  6. <bean id="p30Phone" class="phone.P30Phone"/>
  7. <bean id="mete30Phone" class="phone.Mete30Phone"/>
  8. <bean id="lihua" class="phone.Somebody">
  9. <constructor-arg ref="p30Phone"/>
  10. </bean>
  11. <bean id="xiaoming" class="phone.Somebody">
  12. <constructor-arg ref="mete30Phone"/>
  13. </bean>
  14. </beans>

基于上一节的示例,不用PhoneConfig配置类,并使用ClassPathXmlApplicationContext创建Spring容器,Main方法如下:

  1. package phone;
  2. import org.springframework.context.support.ClassPathXmlApplicationContext;
  3. public class Main {
  4. public static void main(String[] args) {
  5. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("phone/application.xml");
  6. Somebody somebody = (Somebody) context.getBean("lihua");
  7. somebody.usePhone();
  8. Somebody someone = (Somebody) context.getBean("xiaoming");
  9. someone.usePhone();
  10. }
  11. }

运行结果:

  1. 使用 P30 手机呼叫...
  2. 使用 Mete30 手机呼叫...

 

导入和混合配置

在JavaConfig中引用XML

  1. package phone;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. @Configuration
  5. public class PhoneConfig {
  6. @Bean
  7. public P30Phone p30Phone() {
  8. return new P30Phone();
  9. }
  10. @Bean
  11. public Mete30Phone mete30Phone() {
  12. return new Mete30Phone();
  13. }
  14. }

此处只配置Phone的两个Bean。

 

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
  6. <bean id="lihua" class="phone.Somebody">
  7. <constructor-arg ref="p30Phone"/>
  8. </bean>
  9. <bean id="xiaoming" class="phone.Somebody">
  10. <constructor-arg ref="mete30Phone"/>
  11. </bean>
  12. </beans>

XML配置文件配置了"lihua"和"xiaoming"两个Somebody的bean。

 

  1. package phone;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.context.annotation.Import;
  4. import org.springframework.context.annotation.ImportResource;
  5. @Configuration
  6. @Import({PhoneConfig.class})
  7. @ImportResource("classpath:phone/application.xml")
  8. public class SomebodyConfig {
  9. }

配置通过@Import引用Phone的配置,以及通过@ImportResource引用XML的配置

 

  1. package phone;
  2. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  3. public class Main {
  4. public static void main(String[] args) {
  5. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SomebodyConfig.class);
  6. Somebody somebody = (Somebody) context.getBean("lihua");
  7. somebody.usePhone();
  8. Somebody someone = (Somebody) context.getBean("xiaoming");
  9. someone.usePhone();
  10. }
  11. }

运行结果:

  1. 使用 P30 手机呼叫...
  2. 使用 Mete30 手机呼叫...

 

参考《Spring实战(第4版)》

原文链接:http://www.cnblogs.com/jeremyfa/p/11047365.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号