@Autowired用法与原理解析

Posted 流楚丶格念

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了@Autowired用法与原理解析相关的知识,希望对你有一定的参考价值。

文章目录

@Autowired 注解用法

@Autowired 注解,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过 @Autowired的使用来消除 set ,get方法。

在使用@Autowired之前,我们对一个bean配置起属性时,是这样用的:

<property name="属性名" value=" 属性值"/>   

通过这种方式来,配置比较繁琐,而且代码比较多。在Spring 2.5 引入了 @Autowired 注解。

下面用案例来具体说明一下@Autowired的用法

代码案例

定义Bean的接口,其中定义了一个save方法

package com.yyl.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService 

    @Autowired
    private UserRepository userRepository;

    public void save() 
        userRepository.save();
    

定义一个UserRepository接口的实现类,并实现save方法,注意,在这里指定了该bean在IoC中标识符名称为userRepository,后面我们使用的时候可以从容器上下文中获取

package com.yyl.service.impl;

import com.yyl.service.UserRepository;
import org.springframework.stereotype.Repository;

// 指定了该bean在IoC中标识符名称为userRepository
@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository 
    @Override
    public void save() 
        System.out.println("UserRepositorUImpl save");
    

然后我们定义服务类,这里需要一个UserRepository类型的属性实例,通过@Autowired自动装配方式,从IoC容器中去查找到,并返回实例

package com.yyl.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService 

    @Autowired
    private UserRepository userRepository;

    public void save() 
        userRepository.save();
    

然后需要在 applicationContext.xml配置注解扫描的包

<!--配置扫面-->
<!--配置扫描带有四大注解类:@Controller、@Service、@Repository、@Component,交给spring统一管理-->
<context:component-scan base-package="com.yyl.service"></context:component-scan>

测试代码:

@Test
public void AutowiredBean()
    ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
    UserService userService=(UserService) ctx.getBean("userService");
    userService.save(); //结果为UserRepositoryImps save

运行结果如下所示:

@Autowired的原理

其实在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

装配过程如下所示:

然后我们在使用@Autowired时,首先在容器中查询对应类型的bean。如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据如果查询的结果不止一个,那么@Autowired会根据名称来查找。如果查询的结果为空,那么会抛出异常

解决方案:使用required=false,没有就返回空就好,不用报异常

补:@Autowired的require属性

required默认为true,如下源码

当required属性为true的时候,注入SpringBean的时候,该bean必须存在,不然会注入失败,启动报错

当required属性为false的时候,注入SpringBean的时候,如果bean存在,就注入;如果不存在,就忽略跳过,启动不会报错,但不能直接使用

代码案例:多个实现类实例

举例说明: 接着上面的例子,我们在定一个类来实现UserRepository接口

package com.yyl.service.impl;

import com.yyl.service.UserRepository;
import org.springframework.stereotype.Repository;

@Repository()
public class UserAnotherImpl implements UserRepository 
    @Override
    public void save() 
        System.out.println("UserAnotherImpl save");
    

这时在启动容器后,在容器中有两个UserRepository类型的实例,一个名称为userRepository,另一个为UserAnotherImpl。

此时,在UserService中

@Autowired
private UserRepository userRepository; // 输出结果:UserRepositoryImpl save

运行结果:

这里由于查询到有两个该类型的实例,那么采用名称匹配方式,在容器中查找名称为userRepository的实例,并自动装配给该参数。如果这里想要装配UserAnotherImpl的实例,除了可以将字段userRepository名称改成UserAnotherImpl外,还可以提供了一个@Qualifier注解,来指定需要装配bean的名称,代码如下:

我们先给UserAnotherImpl 加一个bean名称

@Repository("userAnotherImpl")
public class UserAnotherImpl implements UserRepository 
    @Override
    public void save() 
        System.out.println("UserAnotherImpl save");
    

再修改注入时代码

@Autowired
@Qualifier("userAnotherImpl")
private UserRepository userRepository; //输出结果:UserAnotherImplsave

运行结果:

以上是关于@Autowired用法与原理解析的主要内容,如果未能解决你的问题,请参考以下文章

@Autowired 与@Resource的区别

@Resource

@Resource

Spring中@Resource与@Autowired@Qualifier的用法与区别

Spring中@Resource与@Autowired@Qualifier的用法与区别

Spring中@Resource与@Autowired@Qualifier的用法与区别