Spring 容器的元数据可以基于注解配置,它比 XML 配置更简洁,而且提供了更多的上下文配置。
两种配置方式各有优缺点,XML 配置不会侵入源代码,配置修改后不需要重新编译源文件。
你可以在项目中任意选择哪种配置方式,或者两者混合使用。
参阅上一篇《Spring基于XML配置的容器》
一、Bean 管理
Spring 通过扫描指定包路径下所有的类(包括子包下的类),来寻找哪些类是要容器管理的。
默认情况下,根据类是否存在 @Component
注解(或其组合注解)来判断是否由容器管理。
1. 扫描类路径配置
基于 XML 配置
在 XML 配置文件中使用 context:component-scan
来配置扫描的包路径。
<beans>
<context:component-scan base-package="cn.codeartist.spring.bean.annotation"/>
</beans>
使用 ClassPathXmlApplicationContext
来实例化容器。
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("bean-annotation.xml");
BeanExample beanExample = (BeanExample) applicationContext.getBean("beanExample");
}
基于注解配置
定义类并使用 @Configuration
和 @ComponentScan
来配置扫描的包路径。
@Configuration
@ComponentScan(basePackages = "cn.codeartist.spring.bean.annotation")
public class AppConfig {
}
@ComponentScan
可以不指定 basePackages,默认扫描类(AppConfig
)所在的包路径。
使用 AnnotationConfigApplicationContext
来实例化容器。
public static void main(String[] args) {
ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(AppConfig.class);
BeanExample beanExample = (BeanExample) applicationContext.getBean("beanExample");
}
2. 使用注解管理 Bean
在扫描的包下面,在类上面使用 @Component
注解来注册 Bean。
@Component
public class BeanExample {
private String name;
private Integer year;
// Getter and setter
}
为了更明确 Bean 的业务用途,体现项目的分层结构,Spring 还提供了 @Service
、@Repository
和 @Controller
等注解。
这些注解默认使用类名小驼峰格式作为 Bean 名称,也可以通过注解的 value
属性来指定。
BeanExample -> beanExample
Bean 作用域
使用 @Scope
注解来指定 Bean 的作用域。
@Component
@Scope("singleton")
public class BeanExample {
private String name;
private Integer year;
}
作用域类型参阅《Spring基于XML配置的容器》
二、依赖管理
在基于 XML 配置容器中,使用 context:annotation-config
来配置注解注入。
<beans>
<context:annotation-config/>
</beans>
如果 XML 配置文件中存在
context:component-scan
,则不需要配置context:annotation-config
。
Spring 通常使用 @Autowired
和 @Resource
注解注入 Bean 依赖,@Autowired
注解默认通过类型注入。
@Resource
注解默认通过名称注入,只有匹配不到对应名称的 Bean,才会按类型注入。
1. 依赖注入
1.1 字段注入
直接在字段上面使用注解注入依赖。
@Component
public class BeanExample {
private String name;
private Integer year;
@Autowired
private BeanProvider beanProvider;
}
1.2 构造器注入
在构造器方法上使用注解注入依赖。
@Component
public class BeanExample {
private String name;
private Integer year;
private BeanProvider beanProvider;
@Autowired
public BeanExample(BeanProvider beanProvider) {
this.beanProvider = beanProvider;
}
}
Spring 4.3.x 版本后,构造器注入可以不用写注解。
1.3 Setter 方法注入
在 Setter 方法上使用注解注入依赖。
@Component
public class BeanExample {
private String name;
private Integer year;
private BeanProvider beanProvider;
@Autowired
public void setBeanProvider(BeanProvider beanProvider) {
this.beanProvider = beanProvider;
}
}
2. 依赖关系
使用 @DependsOn
注解指定依赖关系。
@Component
@DependsOn("beanProvider")
public class BeanExample {
private String name;
private Integer year;
private BeanProvider beanProvider;
// Getter and setter
}
3. 懒加载
使用 @Lazy
注解配置懒加载。
@Lazy
@Component
public class BeanProvider {
// Fields
// Getter and setter
}
懒加载 Bean 在注入的地方也要加上 @Lazy
注解,或者使用 ApplicationContext.getBean()
方法获取 Bean,才能使懒加载生效。
@Component
public class BeanExample {
private String name;
private Integer year;
@Lazy
@Autowired
private BeanProvider beanProvider;
}
三、附录
1. 配置属性
属性 | 描述 |
---|---|
context:component-scan |
在基于 XML 配置容器中,指定扫描包路径 |
context:annotation-config |
在基于 XML 配置容器中,启用注解注入依赖 |
2. 常用注解
注解 | 描述 |
---|---|
@Configuration |
指定 Bean 的配置类 |
@ComponentScan |
(默认为类所在的包)指定包路径,该包下的类由容器管理 |
@Component |
指定该类由 Spring 容器管理 |
@Service |
与 @Component 一致,通常在业务层使用 |
@Repository |
与 @Component 一致,通常在数据层使用 |
@Controller |
与 @Component 一致,通常在控制层使用 |
@Autowired |
配置自动注入,优先通过类型注入 |
@Resource |
配置自动注入,优先通过名称注入 |
@Scope |
指定 Bean 的作用域 |
@DependsOn |
指定 Bean 的依赖关系 |
@Lazy |
配置懒加载 |
3. 示例代码
Gitee 仓库:https://gitee.com/code_artist/spring
项目模块:spring-ioc
示例路径:cn.codeartist.spring.bean.annotation
欢迎关注码匠公众号:CodeArtist,更多干货文章首发!