前面介绍过通过@Import/@ComponentScan+@Component/@Bean/实现FactoryBean接口四种方式可以把bean加到spring的ioc容器中来。
而@AutoWired注解则可以为这些加到容器中的实例的变量,参数,方法进行自动赋值。
主要知识点:
1.@Autowired 默认时根据类型来赋值的,可以使用@Bean(autowire = Autowire.BY_NAME)修改成按照名字来装配。
2. 当在spring容器中有多个类型相同的时候实例时,我们可以在备选的bean上面加上@Primary注解来标识优先选择。
3. 当在spring容器中有多个类型相同的时候实例时可以用@Qualifier指定按名称装配。
4. @Autowired可以放在方法的参数前,当该方法所属的类被初始化时该方法会自动被调用,会自动的给参数赋合适的值。
5. @Autowired可以放在方法上,当该方法所属的类被初始化时该方法会自动被调用,所以可以用它来为某些变量赋值。
6. 当变量上的被@Autowired注解时,如果从spring 容器中找不到合适值来注入时会报错,为了不报错我们可以使用注解@Autowired(required = false),这样有合适的就会注入,没有则放弃,不会报错。
7. @Autowired是spring自带的,@Inject是JSR330规范实现的,@Resource是JSR250规范实现的,需要导入不同的包。
可以了解的知识:@Inject @Inject是默认按照类型匹配的 ,@Inject和@Name一起使用 @Autowired如果需要按照名称匹配需要和@Qualifier,@Resource @Resource是按照名称匹配的
8.@Autowired可以注解到在构造器上。我没有实验成功,稍后再试试。
为了在例子长包含上面说到的所以情况, 下面定义了一个call special srevice的例子,具体类图如下:
首先定义两个接口BeautyGril 漂亮小姐姐和GentleGril 温柔小姐姐。
package com.allen.trainning.spring.autowired.dao;
public interface BeautyGril {
}
package com.allen.trainning.spring.autowired.dao;
public interface GentleGril {
}
定义一个抽象类LittleOlderSiter 小姐姐。
package com.allen.trainning.spring.autowired.dao;
public abstract class LittleOlderSister {
public String name=null;
public void showAbility(){
System.out.println("I can sing a song.");
}
public void sayHello(){
System.out.println("hi handsome, I am " + name);
}
}
丽丽继承了小姐姐抽象类,实现了漂亮女孩接口
package com.allen.trainning.spring.autowired.dao;
public class Lili extends LittleOlderSister implements BeautyGril{
public Lili(){
this.name="Lili";
}
}
路西继承了小姐姐抽象类,实现了漂亮女孩接口
package com.allen.trainning.spring.autowired.dao;
public class Lucy extends LittleOlderSister implements BeautyGril{
public Lucy(){
this.name="Lucy";
}
}
露露 继承了小姐姐抽象类,实现了温柔女孩接口
package com.allen.trainning.spring.autowired.dao;
public class Lulu extends LittleOlderSister implements GentleGril{
public Lulu(){
this.name="Lulu";
}
}
玛丽继承 小姐姐抽象类,实现了温柔女孩接口
package com.allen.trainning.spring.autowired.dao;
public class Mary extends LittleOlderSister implements GentleGril{
public LittleOlderSister forfree;
public Mary(){
this.name="Mary";
}
}
定义一个特殊服务接口,有一个找小姐姐的方法,调用方法会返回一个小姐姐。
package com.allen.trainning.spring.autowired.service;
import com.allen.trainning.spring.autowired.dao.LittleOlderSister;
public interface SpecialService {
public LittleOlderSister findAGril();
}
下面是配置类, 相当于以前的xml配置文件,配置了将哪些类加入到spring容器中。
@ComponentScan(basePackages = {"com.allen.trainning.spring.autowired.dao","com.allen.trainning.spring.autowired.service"})
@Configuration
public class ConfigBeans {
@Bean
public Lili getLili() {
return new Lili();
}
@Bean(autowire = Autowire.BY_NAME)
public Lulu getLulu() {
return new Lulu();
}
@Primary
@Bean
public Lucy getLucy() {
return new Lucy();
}
@Bean
public Mary getMary(@Autowired Lulu lulu) {
Mary mary = new Mary();
mary.forFree=lulu;
return mary;
}
}
下面是天上人间的特殊服务,也继承了特殊服务接口:
@Service
public class HeavenInWorldService implements SpecialService{
@Autowired
public LittleOlderSister defaultOlderSister;
@Autowired
@Qualifier(value="getLulu")
public LittleOlderSister availableOlderSister;
@Autowired
public Lili goldenOlderSister;
public LittleOlderSister findAGril() {
return this.defaultOlderSister;
}
public LittleOlderSister findAGoldenGril() {
return this.goldenOlderSister;
}
public LittleOlderSister findAvailableGril() {
return this.availableOlderSister;
}
}
测试天上人间服务:
public class AutowiredApp {
public static void main(String[] agrs) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigBeans.class);
HeavenInWorldService service = ctx.getBean(HeavenInWorldService.class);
service.findAGoldenGril().sayHello(); //goldenOlderSister
service.findAGril().sayHello(); //defaultOlderSister
service.findAvailableGril().sayHello(); //availableOlderSister
}
}
执行结果:
hi handsome, I am Lili
hi handsome, I am Lucy
hi handsome, I am Lulu
结果分析:
service.findAGoldenGril()返回的应该是goldenOlderSister ,这里的金牌是的类型是Lili,默认按类型自动注入所以这里是丽丽
service.findAGril()返回的应该是defaultOlderSister,该属性的类型是小姐姐,继承了小姐姐的类很多,但是路西上面加了@Primary所以这里找到了路西
service.findAvailableGril()返回的应该是availableOlderSister,该属性的类型也是小姐姐,继承了小姐姐的类很多,但是在该属性起那么加了@Qualifier(value="getLulu"),该注解就是指定按照getLulu这个bean名字自动装配,就不安类型了
@Primary
@Bean
public Lucy getLucy() {
return new Lucy();
}
下面是东莞的特殊服务,继承了特殊服务接口
@Service
public class DongGuanService implements SpecialService{
@Autowired
public LittleOlderSister defaultOlderSister;
@Autowired
public Lucy goldenOlderSister;
public Mary mary;
@Inject
public Lili lili;
@Resource
public Lulu lulu;
@Autowired(required = false)
public String mostPopularName;
public LittleOlderSister findAGril() {
return this.defaultOlderSister;
}
public LittleOlderSister findDefaultGril() {
return mary;
}
@Autowired
public void setMary(Mary mary){
this.mary =mary;
}
public DongGuanService(){
}
}
测试东莞服务接口, 测试了autowired加到方法上,autowired加到方法的参数上,在spring启动的时候就会默认的去调用这2中方法。
public class AutowiredApp {
public static void main(String[] agrs) {
DongGuanService dservice = ctx.getBean(DongGuanService.class);
Mary mary = (Mary)dservice.findDefaultGril();
mary.sayHello(); //set 方法上加autowired
mary.forFree.sayHello(); // 参数上加autowired
System.out.println(dservice.mostPopularName);//显式去掉autowired @Autowired(required = false)
dservice.lili.sayHello();//@Inject
dservice.lulu.sayHello();//@Resource
}
}
测试结果:
hi handsome, I am Lili
hi handsome, I am Mary
hi handsome, I am Lulu
null
hi handsome, I am Lili
hi handsome, I am Lulu
下面是川妹子服务,测试autowire加到构造器上
@Service
public class SiChuanService implements SpecialService {
public LittleOlderSister defaultGril;
@Autowired
public SiChuanService(Lili lili){
this.defaultGril=lili;
}
public LittleOlderSister findAGril() {
return defaultGril;
}
}
测试:
public class AutowiredApp {
public static void main(String[] agrs) {
SiChuanService sservice = ctx.getBean(SiChuanService.class);
sservice.findAGril().sayHello();
}
}
测试结果:
hi handsome, I am Lili
在带有参数的构造器上加autowired 会在创建类时给你找到合适的参数值。