前言
在Spring框架中,有两种对容器的配置和启动方式,一种是基于XML文档的配置方式,一种则是“零配置”,即Java Based Configuration。
而在零配置中,最常见的就是单独使用@Component
(及其等效注解@Controller
、@Repository
、@Service
),或者共同使用@Configuration
和@Bean
注解,这里将全部介绍。同时也会介绍几乎所有常见的注解配置
@Component
该注解是配置Bean的最基本注解,当该注解修饰一个类时,在初始化容器并扫描后,会进行基本的Bean配置。
@Component
public class Person {
private Axe axe;
public void setAxe(Axe axe) {
this.axe = axe;
}
}
这直接就相当于在容器中配置了一个id为person的bean,当然,默认id是类的首字母小写,也可以这样自定义名称:
@Component("person")
至于@Repository
、@Controller
、@Service
都是@Component
的变体,作用完全一致,只是为了便于区分常常用于修饰不同的类型,分别是数据层bean,控制层bean,服务层bean。
@Scope
该注解用于指定被修饰的bean的作用域,Spring中的bean一共有6种作用域:
- singleton单例模式,只生成一个实例
- prototype原型模式,每次获取bean时都会生成一个实例
- request,对于每一个HTTP请求都会生成一个实例
- session,对于每一次HTTP会话都会生成一个实例
- application,对于整个web应用,该bean只生成一个实例
- websocket,对于整个WebSocket通信,该bean只生成一个实例
使用方法就是直接将对应的作用域名称作为value值传给@Scope
:
@Scope("singleton")
@Resource、@Value
这两个注解用于配置依赖项,前者用于注入容器中的bean,后者用于直接注入值。
这里注意@Resource
这个注解默认时byName的,可以通过指定name属性来指定要注入的bean的id是什么,当然也可通过指定type的方式调整为byType注入
@PostConstuct、@PreDestroy
这两个注解用于生命周期回调
@Component
public class Person {
// ...
// ...
@PostConstuct
public void init() {
System.out.println("Doing init method...");
}
@PerDestroy
public void destroy() {
System.out.println("Doing destroy method...");
}
}
@Bean
该注解一般需要配合@Configuration走CGLIB代理才能发挥出更好的作用。
实际上该注解是将该注解修饰的函数的返回值作为bean注册到容器中。
@Configuration
public class MyBean {
@Bean(value = "wood", initMethod = "init")
public Axe getWoodAxe() {
return new WoodAxe();
}
@Bean("axeMan")
public Person getAxeMan(Axe axe) {
return axe::chop;
}
这里注意,当我们使用@Bean注解时,可以通过之前的方式指定生命周期回调,但是也可通过@Bean自带的属性来指定,但是指定的必须是返回值类中有的函数(如果返回值为一个接口,接口中必须有相关的函数)
其次,@Bean注解修饰的函数可以带任意数量的形参,形参会自动执行byType的自动注入,因此需要注意当检测到多个可匹配的类时会报错。
同时,当指定bean的生命周期时,仍然是使用上述@Scope
注解
并且,可以使用name属性指定该bean的名字
使用@Bean({"dataSource", "subsystemA-dataSource", "subsystemB-dataSource"})
这样的形式指定大量别名
使用@Description("Provides a basic example of a bean")
注解进行bean的描述注解
容器的启动
首先抛开SpringBoot的启动方式不谈,我们先来说一下怎么直接启动一个注解相关的Spring容器。
根据官方文档指出,当我们需要使用注解来开发时,应该使用AnnotationConfigApplicationContext
来实例化一个Spring的容器:
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}