乐趣区

spring学习之注入二

@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> 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 的用法,这边不演示了。

退出移动版