@Autowired
@Autowired默认优先按类型去容器中找对应的bean,可以作用在构造函数、成员变量、方法上面,在spring学习之注入这篇已经有例子了,这边不在讲述。
@Autowired有个required属性,默认是true的,也就是说,当注入的bean是空的情况,会报异常,如果我们允许注入的时候为空,那可以直接设置为false。@Autowired(required = false)
此外,我们还可以用@Nullable注解表示允许为空:
@Autowired
public void setMyService(@Nullable MyService myService) {
this.myService = myService;
}
用java8的java.util.Optional
@Autowired
public void setMyService(Optional myService) {
if (myService.isPresent()) {
this.myService = myService.get();
}
}
@Primary
当自动装配的时候,有多个候选对象,那要怎么办呢,@Autowired是根据类型来找对应的bean,如果类型一样的有多个bean,他怎么知道要装配哪个?
可以用@Primary注解,来指定默认装配哪个。
MyBean
public class MyBean {
private String name;
public MyBean(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
MyController
@Controller
public class MyController {
@Autowired
MyBean myBean;
public MyBean getMyBean() {
return myBean;
}
}
MyConfig
@Configuration
@ComponentScan(value="com.learn.annotation2")
public class MyConfig {
@Bean
MyBean zsBean(){
return new MyBean("张三");
}
@Bean
@Primary
MyBean lsBean(){
return new MyBean("李四");
}
}
测试代码
@Test
public void test() {
ApplicationContext app = new AnnotationConfigApplicationContext(MyConfig.class);
MyController myController = app.getBean("myController", MyController.class);
MyBean myBean = myController.getMyBean();
System.out.println(myBean.getName());
}
运行结果如下:
我们这边@Primary注解是在李四上面的,所以输出结果是李四。
@Qualifier
既然有默认的装配类型,那也会让我们自己选择哪个装配组件,这个是通过@Qualifier实现的,和@Autowired一样,可以作用于成员变量、构造函数、方法里。这边只演示成员变量。
MyController,其他不变。
@Controller
public class MyController {
@Autowired
@Qualifier("zsBean")
MyBean myBean;
public MyBean getMyBean() {
return myBean;
}
}
运行结果如下:
这边打印张三,是通过@Qualifier("zsBean")指定的。
@Resource
@Resource是JSR-250的规范。用法同@Autowired,通过name值来装配组件,不支持空。
MyController
@Controller
public class MyController {
@Resource(name = "lsBean")
MyBean myBean;
public MyBean getMyBean() {
return myBean;
}
}
MyConfig
@Configuration
@ComponentScan(value="com.learn.annotation2")
public class MyConfig {
@Bean
@Primary
MyBean zsBean(){
return new MyBean("张三");
}
@Bean
MyBean lsBean(){
return new MyBean("李四");
}
}
测试代码
@Test
public void test() {
ApplicationContext app = new AnnotationConfigApplicationContext(MyConfig.class);
MyController myController = app.getBean("myController", MyController.class);
MyBean myBean = myController.getMyBean();
System.out.println(myBean.getName());
}
运行结果:
虽然@Primary注解在zsBean那边,但是 @Resource(name = "lsBean")直接指定李四,得到的结果是李四。如果不执行name呢,打印出来的是张三。
@Inject和@name
@Inject和@name是JSR-330的规范,如果要使用他,还要引入javax.inject的包,@Inject用法同@Autowired,作用于成员变量、方法、构造函数,可以支持java.util.Optional和@Nullable,但是没有required的属性。@name用法同@Qualifier。
MyController
@Controller
public class MyController {
@Inject
@Named("lsBean")
MyBean myBean;
public MyBean getMyBean() {
return myBean;
}
}
测试代码同上,运行结果如下:
@name除了@Qualifier的性质,还有@Component的用法,这边不演示了。