• Spring详解(九)----Spring Bean的自动装配(基于注解的方式【推荐】)


    1、使用@Autowired注解自动装配

           上一章提到使用@Value注解只能装配普通值,是不能装配对象的,所以这章我们来介绍使用注解自动装配对象,需要使用到@Autowired注解:

    • @Autowired:它默认是按byType进行匹配,可以用于修饰类成员变量(字段)、Setter 方法、构造函数,甚至普通方法,但是前提是方法必须有至少一个参数。

           我们在实际的开发中基本都会使用注解来对对象属性完成自动装配,因为这样可以减少配置的复杂度,所以@Autowired非常的重要!

           ①、作用于类的成员变量(字段)(最常用)

           ---User类:

    @Component(value = "user")
    public class User {
        @Value(value = "2020")
        private int userId;
        @Value(value = "是菜逼唐")
        private String userName;
        @Value(value = "20")
        private int userAge;
        @Value(value = "123456")
        private String userPwd;
        @Value(value = "地球中国北京")
        private String userAddress;
    
        //这里使用@Autowired注解自动注入
        @Autowired
        private GirlFriend girlFriend;
    
        //getter、setter、toString方法省略......
    }

           ---GirlFriend类:

    @Component
    public class GirlFriend {
        @Value("王美丽")
        private String girlName;
        @Value("18")
        private int girlAge;
        @Value("170")
        private String girlHeight;
    
        //getter、setter、toString方法省略......
    }

           ---测试代码(扫描组件注解参考上一章):

    /**
     * 测试代码
     */
    public class SpringTest1 {
        public static void main(String[] args) {
            //1.初始化Spring容器,通过注解加载
            ApplicationContext applicationContext = new AnnotationConfigApplicationContext(PojoConfig.class);
            //2.通过容器获取实例
            User user =  applicationContext.getBean("user", User.class);
            //3.调用实例中的属性
            System.out.println(user.getUserId()+"----"+
                            user.getUserName()+"----"+
                            user.getUserAge()+"----"+
                            user.getGirlFriend());
        }
    }

           ---运行测试代码,查看控制台打印的结果:

    image


           ②、作用于Setter方法和作用于构造函数。这两种方式实现的效果和上面的效果是一模一样的。

           1)、作用于Setter方法

    image

           2)、作用于构造函数

           注意:如果已经使用注解完成了初始化工作,那么则不能再创建该参数的构造方法了,比如我们使用了@Value注解初始化userName属性,那么则就不能再创建userName属性的构造方法了。

    image

           可以明显的分析,后面两种方式的可读性并不高,所以一般都推荐使用第一种方式,作用于类的成员变量。


           补充1:@Autowired注解中有个属性required,这个属性是一个boolean类型,为true(默认)表示注入bean的时候该bean必须存在,不然就会注入失败,但程序不报错 。为 false 表示注入bean的时候如果bean存在,就注入成功,如果没有就忽略跳过,启动时不会报错!但是不能直接使用,因为bean为NULL!

           例如我将GirlFriend类的@Component注解给注释掉,并且把User类中的@Autowired注解的属性required设置为false。

    image

           ----------------------------------------

    image

           通过运行的结果可以发现注入失败了。

    image


           补充2:@Autowired注解并不是完全按照byType进行匹配。而是默认先按byType进行匹配,如果发现找到多个bean,则又按照byName方式进行匹配,如果还有多个,则报出异常。动手能力强的可以自己去实践一遍,我自己是去验证过的。

    2、@Autowired自动装配的歧义性

           由于@Autowired注解是根据类型来自动装配的,所以肯定会存在有多个相同类型的bean,而Spring IOC容器却不知要选择哪一个的情况,此时就产生了歧义性,那么我们怎么来解决呢?Spring中给我们提供了@Primary和@Qualifier这两个注解。

    • @Primary:表示优先使用该注解标志的bean。实际开发中不实用,所以就不介绍了。
    • @Qualifier:表示当容器中存在多个相同类型的bean时,使用这个注解可以根据bean的名字来选择注入哪个bean,推荐使用这种方式。

           因为这里的代码不好举例,所以可以参考这个链接:https://blog.csdn.net/qq_36567005/article/details/80611139

    3、与@Autowired类似的注解@Resource

           @Resource 注解相当于@Autowired,它们两个都是用来实现依赖注入的。只是@AutoWried默认按byType自动注入,而@Resource默认按byName自动注入。而且@Resource只能处理setter注入(包括字段)。@Resource有两个重要属性,分别是name和type,其中name属性相当于@Qualifier,type相当于根据类型配置。Spring 将 name 属性解析为bean的名字,而type属性则被解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,如果使用type属性则使用byType的自动注入策略。如果都没有指定,则通过反射机制使用byName自动注入策略。表面上我们说@Resource默认按byName自动注入,其实如果按名称查找不到匹配的bean时,最后会按byType进行自动注入,@Resource依赖注入时查找bean的规则如下:

    • 如果不指定name属性,也不指定type属性,则自动按byName方式进行查找。如果没有找到符合的bean,则回退为一个原始类型进行进行查找,如果找到就注入。
    • 只是指定了@Resource注解的name属性,则只能按name后的名字去bean元素里查找有与之相等的name属性的bean,如果找不到则会抛出异常。
    • 只指定@Resource注解的type属性,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常。
    • 既指定了@Resource的name属性又指定了type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。


           补充:但是我好像听说这个注解在Java11中被删除了,也不知道是不是真的,如果是真的还是慎用!然后我去查了一下JDK11的官方文档,确实JDK11将javax.annotation这个包移除了,如果想继续使用可以通过maven或者其他方式导入。

    <dependency>
        <groupId>javax.annotation</groupId>
        <artifactId>javax.annotation-api</artifactId>
        <version>1.3.2</version>
    </dependency>

           如果这个依赖无法使用,可以去maven仓库自行查找。

    4、@Autowired和@Resource的区别

          相同点:

    • 二者均可以用来注入bean,都可以用在字段上或者方法上

           不同点:

    • @Autowired是属于Spring框架的,而@Resource属于J2EE。
    • @Autowired默认按byType进行装配,可以结合@Qualifier使用按名称装配,如果发现找到多个bean,则又按照byName方式进行匹配,如果还有多个,则报出异常。
    • @Resource默认按byName进行装配,名称可以通过name属性进行指定,如果没有指定name属性,则默认采用字段名进行查找,当找不到与名称匹配的bean时才按byType进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

           小结:@Autowired是按照先按 byType 后按 byName 进行匹配,@Resources是按照先按 byName 后按 byType进行匹配。

    5、@Named/@Inject(了解)

           这两个注解的是JSR-330的一部分,而Spring 是支持JSR-330的。这些注解在使用上和Spring的注解一样,只是想要导入额外的相关jar包。如下:

            <!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
            <dependency>
                <groupId>javax.inject</groupId>
                <artifactId>javax.inject</artifactId>
                <version>1</version>
            </dependency>
    • @Named 用来替代@Component 声明一个Bean
    • @Inject 用来替代@Autowired来执行注入

           实际上我们很少会使用这样的注解,使用知道有这个东西即可。


           参考链接:

  • 相关阅读:
    计算机问题:VirtualBox启动崩溃问题
    软件工程:代码静态分析工具
    oracle 游标
    oracle 控制语句
    oracle 数据类型及函数
    oracle 表空间Tablespaces
    java.lang.RuntimeException: java.sql.SQLSyntaxErrorException: ORA-00911: 无效字符
    oracle 用户解锁和修改用户密码
    shiro + maven 的web配置(不整合spring)
    配置shiro错误
  • 原文地址:https://www.cnblogs.com/tanghaorong/p/14165477.html
Copyright © 2020-2023  润新知