注解方式配置Spring容器
注解方式配置Spring容器
注解方式配置 Spring 容器可以完全替代传统的 XML 配置文件。只需要定义一个配置类,并在配置类上使用注解来指定扫描的包,Spring 就会自动扫描并注册这些包下的组件(如 @Component、@Service、@Repository 等)
核心步骤
-
导入依赖
-
定义一个配置类
-
使用
@Configuration注解标记一个类为配置类。这个类的作用类似于 XML 配置文件 -
@Configuration @ComponentScan(basePackages = "com.example") // 指定扫描的包 public class AppConfig { } -
@Configuration:标记该类为 Spring 的配置类。 -
@ComponentScan:指定 Spring 扫描的包路径,Spring 会自动注册这些包下的组件。 -
@PropertySource注解:在Java配置类使用
@PropertySource注解,显式指定配置文件的位置-
@Configuration //加载单个 @PropertySource("classpath:application.properties") //加载多个 @PropertySource({"classpath:application.properties", "classpath:another.properties"}) public class AppConfig { } -
@PropertySource默认只支持properties文件。如果需要加载YAML文件,需要额外配置
-
-
-
在组件上使用注解
- 在需要被 Spring 管理的类上使用以下注解:
@Component:通用组件。@Service:服务层组件。@Repository:持久层组件。@Controller:控制层组件(通常用于 Spring MVC)。
- 在需要被 Spring 管理的类上使用以下注解:
-
使用 @Autowired 注入依赖
-
在需要注入依赖的地方使用
@Autowired注解。Spring 会自动查找匹配的 Bean 并注入 -
@Service public class UserService { private final UserRepository userRepository; @Autowired public UserService(UserRepository userRepository) { this.userRepository = userRepository; } }
-
-
启动 Spring 容器
-
使用
AnnotationConfigApplicationContext加载配置类,启动 Spring 容器 -
public class MainApp { public static void main(String[] args) { // 加载配置类,初始化 Spring 容器 ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 从容器中获取 Bean UserService userService = context.getBean(UserService.class); // 使用 Bean userService.doSomething(); } }
-
-
混合使用 XML 和注解
-
如果需要,可以同时使用注解和 XML 配置。在配置类中使用
@ImportResource导入 XML 配置文件 -
@Configuration @ComponentScan(basePackages = "com.example") @ImportResource("classpath:applicationContext.xml") // 导入 XML 配置文件 public class AppConfig { }
-
常见注解
-
@Component
-
作用: 标记一个类为 Spring 容器管理的 Bean。
-
使用场景: 通用的组件,不特定于服务层、持久层或控制器层。
-
@Component public class MyComponent { // 类内容 } -
Bean的名称
-
默认情况下,Spring 会将类名的首字母小写作为 Bean 的名称。例如,
MyComponent类的 Bean 名称是myComponent。也可以通过@Component注解的value属性指定 Bean 的名称 -
Spring用map集合存储所有的Bean,键就是Bean的名称
-
@Component("customBeanName") public class MyComponent { // 类的内容 }
-
-
-
@Service:标记一个类为服务层的 Bean
-
@Repository:标记一个类为持久层的 Bean
-
@Controller:标记一个类为控制层的 Bean,用于处理 HTTP 请求(通常在 Spring MVC 中使用)
-
@Bean
-
作用: 标记一个方法返回的对象为 Spring 容器管理的 Bean。
-
使用场景: 用于配置类中定义 Bean。
-
在
@Configuration类中,@Bean方法会被Spring通过CGLIB代理增强,确保每次调用@Bean方法时返回的是同一个单例Bean(除非显式指定@Scope为prototype) -
@Component类中的@Bean方法不会被CGLIB代理增强。因此,如果多次调用@Bean方法,可能会创建多个实例(除非手动确保单例行为) -
如果
@Bean方法所在的类没有@Configuration或@Component注解,可以通过@Import将其导入到配置类中 -
public class MyConfig { @Bean public MyService myService() { return new MyService(); } } @Configuration @Import(MyConfig.class) public class AppConfig { } -
@Bean方法的参数注入机制-
当 Spring 容器调用
@Bean方法时,它会:-
解析方法参数:根据参数类型从容器中查找匹配的 Bean。
- 默认情况下,Spring 会根据类型注入。
- 如果存在多个相同类型的 Bean,Spring 会根据参数名称注入。
-
自动注入:将找到的 Bean 作为参数传递给
@Bean方法。 -
@Bean public UserService userService(UserRepository userRepository) { return new UserService(userRepository); } -
UserRepository userRepository参数会被 Spring 自动注入。
-
-
-
-
@Configuration
-
作用: 标记一个类为配置类,通常与
@Bean注解一起使用。 -
使用场景: 用于定义 Bean 的配置。
-
@Configuration public class MyConfig { @Bean public MyBean myBean() { return new MyBean(); } } //Spring 会使用该((方法名))作为 Bean 的名称 //自定义Bean名称 @Configuration public class MyConfig { @Bean("customBeanName") public MyBean myBean() { return new MyBean(); } }
-
-
@Conditional
-
根据条件决定是否注册某个 Bean
-
@Bean @Conditional(MyCondition.class) public MyBean myBean() { return new MyBean(); }
-
-
@Scope
-
作用: 定义 Bean 的作用域(如单例、原型等)。
-
使用场景: 用于指定 Bean 的生命周期。
-
@Component @Scope("prototype") public class MyComponent { // 类内容 }
-
-
@Primary
- 作用: 当有多个相同类型的 Bean 时,优先使用标记为
@Primary的 Bean。 - 使用场景: 用于指定默认的 Bean。
- 作用: 当有多个相同类型的 Bean 时,优先使用标记为
-
@PostConstruct 和 @PreDestroy
-
作用: 分别标记在 Bean 初始化和销毁时执行的方法。
-
使用场景: 用于生命周期回调。
-
@Component public class MyComponent { @PostConstruct public void init() { // 初始化逻辑 } @PreDestroy public void destroy() { // 销毁逻辑 } }
-
依赖注入
所有注入方式的前提条件:类必须由 Spring 管理
Spring支持以下几种依赖注入的方式:
-
字段注入
-
构造方法注入
@Service public class MyService { private final MyRepository myRepository; private final MyComponent myComponent; @Autowired public MyService( @Qualifier("myRepositoryImpl") MyRepository myRepository, @Qualifier("myComponentImpl") MyComponent myComponent ) { this.myRepository = myRepository; this.myComponent = myComponent; } } -
Setter方法注入
-
条件化注入
方法注入
-
当
@Autowired注解用于普通方法时,Spring 会将匹配的 bean 注入到方法的参数中-
@Autowired public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; }- 方法的参数类型是
UserRepository。 - Spring 会在容器中查找类型为
UserRepository的 bean。 - 如果找到唯一一个匹配的 bean,Spring 会将其注入到方法参数中。
- 方法的参数类型是
-
-
方法名无关紧要:Spring 只关心方法的参数类型,而不是方法名。方法名可以是任意的(例如
setUserRepository、init等)。-
如果有该方法上存在@Bean注解的话方法名会被当作该Bean的默认名称
-
方法参数必须匹配:方法的参数类型必须与 Spring 容器中的 bean 类型匹配。如果有多个匹配的 bean,需要使用
@Qualifier注解指定具体的 bean。-
@Service public class UserService { private UserRepository userRepository; @Autowired public void setUserRepository(@Qualifier("jdbcUserRepository") UserRepository userRepository) { this.userRepository = userRepository; } }
-
-
按照注入属性值类型的划分:
-
普通类型的属性注入
-
普通类型包括基本数据类型(如
int、boolean等)及其包装类(如Integer、Boolean等),以及字符串(String) -
使用@Value注解,
@Value注解用于注入普通类型的值,可以直接注入字面量,也可以注入配置文件中的属性值 -
@Service public class MyService { // 注入字面量 @Value("100") private int maxUsers; // 注入字符串 @Value("Hello, World!") private String greeting; // 注入配置文件中的属性值 @Value("${app.name}") private String appName; // 注入默认值(如果配置文件中没有app.version,则使用默认值1.0.0) @Value("${app.version:1.0.0}") private String appVersion; }
-
-
对象类型的注入
-
使用@Autowired注解
-
@Autowired注解用于自动注入对象类型的属性。默认按类型(byType)进行注入 -
@Service public class UserService { @Autowired private UserRepository userRepository; public void doSomething() { userRepository.save(); } } @Repository public class UserRepository { public void save() { System.out.println("User saved!"); } }
-
-
使用@Qualifier注解
-
如果有多个相同类型的Bean,可以使用
@Qualifier注解指定具体的Bean名称 -
@Service public class UserService { @Autowired @Qualifier("userRepositoryImpl") private UserRepository userRepository; } @Repository("userRepositoryImpl") public class UserRepositoryImpl implements UserRepository { public void save() { System.out.println("User saved by UserRepositoryImpl!"); } } @Repository("anotherUserRepository") public class AnotherUserRepository implements UserRepository { public void save() { System.out.println("User saved by AnotherUserRepository!"); } }
-
-
-
集合类型的注入
-
普通值类型集合的注入
-
对象集合类型的注入
-
可以直接注入一个
List或Set,Spring会自动将所有匹配的Bean注入到集合中 -
@Service public class MyService { @Autowired private List<UserRepository> userRepositories; @Autowired private Set<UserRepository> userRepositorySet; } @Repository public class UserRepositoryImpl implements UserRepository { public void save() { System.out.println("User saved by UserRepositoryImpl!"); } } @Repository public class AnotherUserRepository implements UserRepository { public void save() { System.out.println("User saved by AnotherUserRepository!"); } } -
可以注入一个
Map,其中键是Bean的名称,值是Bean的实例-
@Service public class MyService { @Autowired private Map<String, UserRepository> userRepositoryMap; }
-
-
-
Autowired和Resource 注解
-
@Autowired 注解
-
@Autowired是 Spring 框架提供的注解,用于实现依赖注入。它可以标注在字段、构造方法、Setter 方法或普通方法上,Spring 会根据类型自动匹配并注入 Bean -
注入规则
-
按类型注入:
@Autowired默认根据类型(byType)进行注入。如果容器中存在多个相同类型的 Bean,Spring 会抛出NoUniqueBeanDefinitionException异常。 -
解决歧义:如果有多个相同类型的 Bean,可以通过以下方式解决:
-
使用
@Qualifier注解指定 Bean 的名称。 -
@Autowired @Qualifier("myRepositoryImpl") private MyRepository myRepository; -
将目标 Bean 标记为
@Primary,表示优先注入 -
@Primary @Repository public class MyRepositoryImpl implements MyRepository { // 实现 }
-
-
-
其他特性
-
required 属性:
@Autowired默认是必须注入的(required=true),如果找不到匹配的 Bean,会抛出异常。可以通过required=false设置为非必须注入。 -
@Autowired(required = false) private MyRepository myRepository; -
构造方法注入推荐:Spring 官方推荐使用构造方法注入,因为它可以保证依赖不可变,并且更容易进行单元测试。
-
-
-
@Resource 注解
-
@Resource是 Java 标准注解(javax.annotation.Resource),Spring 也支持它。它的作用与@Autowired类似,但注入规则不同 -
特点
-
按名称注入:
@Resource默认根据名称(byName)进行注入。如果未指定名称,则根据字段名或方法名匹配 Bean 的名称。@Component public class MyController { @Resource(name = "myService") // 显式指定名称 private MyService service; public void execute() { service.doSomething(); } } @Component public class MyController { @Resource // 未指定名称 private MyService myService; // 字段名为 myService public void execute() { myService.doSomething(); } } -
按类型注入:如果未找到匹配名称的 Bean,则会退回到按类型(
byType)注入。 -
不支持构造方法注入:
@Resource不能用于构造方法注入。 -
无
required属性:@Resource没有required属性,如果找不到匹配的 Bean,会抛出异常
-
-

浙公网安备 33010602011771号