Spring 全注解配置 bean 和 调用 (4) @Primary 自动装配歧义性

本文通过一个具体的示例展示了如何使用Spring框架进行依赖注入。在示例中,创建了一个Car类,该类包含三个CarComponent类型的成员变量:wheels、steer和engine,并通过@Autowired注解实现了自动装配。
package com.xiuye.bean;

import org.springframework.beans.factory.annotation.Autowired;

import com.xiuye.component.CarComponent;

public class Car {

	private CarComponent wheels;
	private CarComponent steer;
	private CarComponent engine;

	@Autowired
	public void setWheels(CarComponent wheels) {
		this.wheels = wheels;
	}
	@Autowired
	public void setSteer(CarComponent steer) {
		this.steer = steer;
	}
	@Autowired
	public void setEngine(CarComponent engine) {
		this.engine = engine;
	}

	public void configInfo(){
		this.steer.description();
		this.wheels.description();
		this.engine.description();
	}




}

package com.xiuye.component;

public interface CarComponent {

	public void description();
}

package com.xiuye.component;

import org.springframework.stereotype.Component;

@Component
public class CarSteerComponent implements CarComponent {

	@Override
	public void description() {
		System.out.println("I'm car's steer!");
	}

}

package com.xiuye.component;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

@Component
@Primary
public class CarEngineComponent implements CarComponent {

	@Override
	public void description() {

		System.out.println("I'm car's engine!");

	}

}

package com.xiuye.component;

import org.springframework.stereotype.Component;

@Component
public class CarWheelComponent implements CarComponent {

	@Override
	public void description() {
		System.out.println("I'm car's wheels!");
	}

}

package com.xiuye.config;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.Scope;

import com.xiuye.bean.Car;
import com.xiuye.bean.Student;
import com.xiuye.component.ComponentForStudent2;
import com.xiuye.config.condition.StudentCondition;

@Configuration
@ComponentScan("com.xiuye.component")
@Profile("dev")
public class BeanConfiguration1 {

	@Bean
	@Conditional(StudentCondition.class)
	public Student student() {
		return new Student("xiuye", "man", 18, 99);
	}

	/**
	 * @param name
	 * @param sex
	 * @param age
	 * @param level
	 * @return
	 */
	@Bean
	@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) // 必须原生,否则no longer has
													// any effect
	public Student student(String name, String sex, int age, int level) {
		return new Student(name, sex, age, level);
	}

	@Bean
	public ComponentForStudent2 cfs2(Student s) {
		ComponentForStudent2 cfs2 = new ComponentForStudent2();
		cfs2.setStudent(s);
		return cfs2;
	}

	@Bean
	public Car car(){
		return new Car();
	}

}

package com.xiuye.test;

import javax.annotation.Resource;

import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.xiuye.bean.Car;
import com.xiuye.component.ComponentForStudent;
import com.xiuye.component.ComponentForStudent2;
import com.xiuye.config.BeanConfiguration1;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=BeanConfiguration1.class)
@ActiveProfiles("dev")

public class TestMain {


	@Resource
	private ComponentForStudent cfs;
	@Resource
	private ComponentForStudent2 cfs2;

	@Resource
	private Car car;

	@BeforeClass
	public static void envConfig(){
		System.setProperty("test","true");
	}

	@Test
	public void testCfs(){
		cfs.studentInfo();
	}
	@Test
	public void testCfs2(){
		cfs2.studentInfo();
	}


	@Test
	public void testCar(){
		this.car.configInfo();
	}

}

十一月 12, 2016 1:00:26 下午 org.springframework.test.context.support.DefaultTestContextBootstrapper getDefaultTestExecutionListenerClassNames
信息: Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
十一月 12, 2016 1:00:26 下午 org.springframework.test.context.support.DefaultTestContextBootstrapper instantiateListeners
信息: Could not instantiate TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [javax/servlet/ServletContext]
十一月 12, 2016 1:00:26 下午 org.springframework.test.context.support.DefaultTestContextBootstrapper getTestExecutionListeners
信息: Using TestExecutionListeners: [org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@133c8f8, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@1a25848, org.springframework.test.context.support.DirtiesContextTestExecutionListener@c3fd8b, org.springframework.test.context.transaction.TransactionalTestExecutionListener@194a1b5, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@5fc7f7]
十一月 12, 2016 1:00:26 下午 org.springframework.context.support.GenericApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.GenericApplicationContext@25790e: startup date [Sat Nov 12 13:00:26 CST 2016]; root of context hierarchy
Active profile := dev
test := true
I'm car's engine!
I'm car's engine!
I'm car's engine!
十一月 12, 2016 1:00:26 下午 org.springframework.context.support.GenericApplicationContext doClose
信息: Closing org.springframework.context.support.GenericApplicationContext@25790e: startup date [Sat Nov 12 13:00:26 CST 2016]; root of context hierarchy
注:三个注入的CarComponent都是CarEngineComponent
<think>嗯,用户让我介绍一下Spring Bean的装配,我得先理清楚这个主题的主要点。Spring Bean的装配方式主要有三种:XML配置、注解配置Java配置。可能用户对Spring有一定的基础,但需要更系统的了解。 首先,XML配置是传统的方式,记得要提到<bean>标签ApplicationContext的使用。然后注解配置,比如@Component@Autowired,还有组件扫描的重要。接着是Java配置类,用@Configuration@Bean来定义,这种方法更灵活,适合现代开发。 用户可能想知道不同装配方式的优缺点,或者在不同场景下如何选择。比如XML适合集中管理配置,注解Java配置更便捷。可能还要提到自动装配的模式,比如byName、byType,以及@Primary@Qualifier解决冲突的方法。 另外,用户可能对装配的过程不太清楚,需要解释容器如何创建管理Bean的生命周期。或者他们可能遇到Bean冲突的问题,如何解决依赖注入时的歧义。举例子会有帮助,比如用XML定义Bean,用注解自动装配,用Java配置类替代XML。 还要注意术语的准确,确保每个概念都解释清楚,比如ApplicationContext的作用,@ComponentScan的用途,以及@Bean方法的返回值成为Bean实例。可能需要比较不同配置方式的适用场景,帮助用户根据项目需求选择合适的方法。 最后,用户可能想了解自动装配的常见问题及解决方案,比如多个候选Bean时的处理,或者循环依赖的问题。虽然问题中没有提到,但简要提及这些可以增加回答的全面。 总之,结构要清晰,分点介绍三种装配方式,每种方式的配置方法、示例适用场景,最后总结如何选择。语言要简洁,避免技术术语堆砌,让不同层次的读者都能理解。确保涵盖核心概念,帮助用户建立对Spring Bean装配的整体认识。</think>Spring Bean 的装配是 Spring 框架的核心机制之一,指的是将对象的创建、依赖注入及生命周期管理交由 Spring 容器(IoC 容器)控制的过程。以下是 Spring Bean 装配的常见方式核心概念: --- ### **1. 装配的三种主要方式** #### **(1) XML 显式配置** - **定义**:通过 XML 文件手动声明 Bean 及其依赖关系。 - **关键标签**: ```xml <!-- 定义 Bean --> <bean id="userService" class="com.example.UserServiceImpl"> <!-- 依赖注入(构造器注入) --> <constructor-arg ref="userRepository"/> </bean> <!-- 定义依赖的 Bean --> <bean id="userRepository" class="com.example.UserRepositoryImpl"/> ``` - **特点**:集中管理配置,适合大型项目,但维护成本较高。 #### **(2) 注解配置(隐式装配)** - **组件扫描**:通过 `@ComponentScan` 自动发现并注册 Bean。 - **常用注解**: - `@Component`:标记类为 Spring Bean。 - `@Autowired`:自动注入依赖(按类型优先)。 - `@Service`, `@Repository`, `@Controller`:`@Component` 的特化形式,用于分层架构。 ```java @Service public class UserServiceImpl implements UserService { @Autowired private UserRepository userRepository; } ``` - **特点**:简化配置,依赖关系通过代码直接体现。 #### **(3) Java 配置类** - **使用 `@Configuration` `@Bean`**:通过 Java 类定义 Bean。 ```java @Configuration public class AppConfig { @Bean public UserRepository userRepository() { return new UserRepositoryImpl(); } @Bean public UserService userService() { return new UserServiceImpl(userRepository()); } } ``` - **特点**:类型安全、灵活,适合替代 XML 配置。 --- ### **2. 自动装配模式** Spring 支持通过 `@Autowired` 或 XML 的 `autowire` 属自动注入依赖,常见策略: - **byType**:按类型匹配(默认)。 - **byName**:按 Bean 名称匹配。 - **constructor**:通过构造器注入。 **解决歧义**: - `@Primary`:标记优先使用的 Bean。 - `@Qualifier("beanName")`:指定具体 Bean 的名称。 --- ### **3. Bean 的作用域** - **单例(Singleton)**:默认作用域,容器中仅一个实例。 - **原型(Prototype)**:每次请求创建新实例。 - **其他**:如 `request`(Web 请求)、`session`(用户会话)等。 --- ### **4. Bean 的生命周期** 1. **实例化**:通过构造器或工厂方法创建对象。 2. **属注入**:填充依赖(如 `@Autowired`)。 3. **初始化**:调用 `@PostConstruct` 或 `InitializingBean` 接口。 4. **销毁**:调用 `@PreDestroy` 或 `DisposableBean` 接口。 --- ### **5. 装配方式的选择建议** - **小型项目**:优先使用 **注解 + 组件扫描**(简洁高效)。 - **第三方库集成**:使用 **Java 配置类**(类型安全)。 - **遗留系统维护**:可能需要 **XML 配置**。 --- ### **示例对比** ```java // 注解方式 @Repository public class UserRepositoryImpl implements UserRepository { ... } @Service public class UserServiceImpl { @Autowired private UserRepository userRepository; } // Java 配置类方式 @Configuration public class AppConfig { @Bean public UserRepository userRepository() { return new UserRepositoryImpl(); } } ``` --- 通过灵活组合这些方式,Spring 实现了高度解耦的组件管理,开发者可以专注于业务逻辑而非对象创建细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值