Spring-@Autowired

@Autowired

 

自动装配(Autowired) 是Spring 提供的一个注解,其实在JDK 中也提供了两个注解来实现类似的功能:@Resource  @Inject 。目的是为了实现依赖注入(Dependence Injection)【在系统运行中,动态的向某个对象提供它所需要的其他对象】 , 在讲到 IOC(Inversion of Control,控制反转) 时的核心知识点 。

 

开始之前我先引用  大牛 开涛老师 对 IOC、DI 的讲解吧

IOC(Inversion of Control):IOC并不是一种技术,他只是一种设计思想。意味着你在 Spring 创建好的对象交给容器控制,而不是如传统方式,由你自己直接控制。那么 IOC 设计思想中,是谁控制了谁?什么是反转?

谁控制谁?IOC 容器控制了容器对象,创建的容器都将自动交给IOC容器进行控制。控制它们的外部资源获取等。

什么是反转?容器帮忙创建以及注入对象。

 


目录

@Autowired

@Autowired 注解定义

工作机制展示

源码分析


 

在分析源码之前我们先看一下他的定义以及工作机制

@Autowired 注解定义

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;
}

可以看出 Autowired 是作用与运行时: @Retention(RetentionPolicy.RUNTIME)

可以作用的范围:构造器(ElementType.CONSTRUCTOR)、方法(ElementType.METHOD)、参数(ElementType.PARAMETER)、属性(ElementType.FILED)、注解类(ElementType.ANNOTATION_TYPE)

 

工作机制展示

 这里我们实现将动物注入给人,为人类服务

首先定义两个接口:Person Animal

Person

public interface Person{
    void service();
    void setAnimal(Animal animal);
}

Animal

public interface Animal{
    void use();
}

然后我们开始创建实现类

BussinessPerson

@Component
public class BussinessPerson implatements Person{

    /**注入动物*/
    @Autowired
    private Animal animal;
    
    @Overide
    public void service(){
        this.animal.use();
    }
    
    @Overide
    public void setAnimal( Animal animal){
        this.animal = animal;
    }
}

Dog

@Component
public class Dog implaments Animal{
    @Overide
    public void use(){
        System.out.println("狗["+Dog.class.getSimpleName()+"]是来看门的");
    }
}

此时我们创建一个测试Test

/*
 * AppConfig.java
 * @ComponentScan(basePackage={"人和动物实现类的包"})
 * @Configuration
 * public class AppConfig(){}
 *
 */

@Test
public void test01(){
    ApplicationContext applicationContext = new AnnocationConfigApplicationContext(AppConfig.class);
    Person person = applicationCOntext.getBean(BussinessPerson.class);
    person.service();
}

可以看到我们此时并没有主动去创建动物对象,但是控制台输出了这么一行

狗[Dog]是来看门的

这是为什么呢?为什么连名字都有了?

名字:默认由实体类的类名,可以在注入的时候为其设置名字(BussinessPeron内的属性字段):

@Qualifier("dog1")
private Animal animal;

然后你就会发现控制台输出就变为了 狗[gog1]是来看门的

为什么自动就选择了狗呢?

其实 @Autowired 是默认按类型 注入的,此时你在Dog的旁边创建一个 Cat,这时就会报错了,因为不知道你要注入的到底是cat 还是dog。在按类型不能注入的时候,会选择按名称注入,将上面属性名从 (BussinessPeron内的属性字段) animal 改为 dog 或 cat 就会注入 Dog 或 Cat

Cat

@Component
public class Cat implements Animal{
    public void use() {
        System.out.println("猫["+ Cat.class.getSimpleName()+"]是来摸的");
    }
}

 报错信息:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bussinessPerson': Unsatisfied dependency expressed through field 'animal'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'cn.dcpnet.attest.Animal' available: expected single matching bean but found 2: cat,dog

 可以看到容器并不知道你要哪一个动物,此时我们将BussinessPerson中属性上加入

private Animal dog;//这里注入的是dog

private Animal cat;//这里注入的是cat

@Qualifier("cat")
private Animal dog;//这里注入的是cat

如果你的名字是 dog ,就会看到控制台输出 狗[Dog]是来看门的   ,如果你的名字是cat ,那么你将看到的是 猫[Cat]是来摸的 

    /**注入动物*/
    @Autowired
    @Qualifier("cat")
    private Animal dog;

 输出

猫[Cat]是来摸的

Process finished with exit code 0

当然你也可以通过配置@Primary 来标志首选注解,如果在 cat上配置了,那么在不指定的情况下都是注解的 cat:

@Primary
@Component
public class Cat implements Animal{
//....
}

/*
 *BussinessPerson 中保持最开始不变
 *  /**注入动物*/
 *  @Autowired
 *  private Animal animal;
 */

输出

猫[Cat]是来摸的

Process finished with exit code 0

还记得源码里面右一句  boolean required() default true;   吗,这是你告诉容器,require为true的时候必须找到对应对象,而为false的时候,没有找到注入也不会报错,当然你用到了这个东西就会抛出空指针异常。

 

源码分析

在Autowired 注解类源码上看到有这么一句话 

@see AutowiredAnnotationBeanPostProcessor

这个是处理Autowired注解的Bean后置处理器

 

正在编写中。。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值