三 Spring 注解 第3.2 之 @Autowire 和 @Resource

                                       三 Spring 注解 

第3.2 之 @Autowire 和 @Resource
@Autowired 或 @Resource 可修饰变量\方法\构造函数,用于完成自动装配(将需要的外部资源注入)
@Autowired Class_A a : 默认按照类型byType

    Qualifier和Autowired配合使用,可以指定bean的byname
    只包含一个:required,默认true开启自动准入,依赖对象必须存在,若要允许null值,改为flase
    用在 构造器、方法、参数、成员变量和注解上
    spring定义的注解
    AutoWiredAnnotationBeanPostProcessor是处理@AutoWired注解的


@Resource Class_A a:  默认用来指定名称byname注入
    包含七个参数,其中最重要的两个参数是:name 和 type。
    用在:类、成员变量和方法上
    @Resource是JDK定义的注解
    CommonAnnotationBeanPostProcessor是处理@ReSource注解的
    @Resource的匹配逻辑为byName -> byType -> byName

有多个bean时,可以在Class_A 上增加@Primary 优先装配A,来避免匹配失败

3.2.1 @Autowire

  • @Autowired装配失败,装配的对象还是null
    原因:
    ① 类上面忘了加@Component(@Service、@Repository @Controller) @Configuration等注解,spring就无法完成自动装配的功能
    ② 注解未被@ComponentScan扫描 ,或者@ComponentScan注解扫描的路径不对
    ③ 注入Filter或Listener
    (web应用启动的顺序是:listener->filter->servlet)
    springmvc的启动是在DisptachServlet里面做的,而它是在listener和filter之后执行。若在listener和filter里面
    @Autowired某个bean时bean还没有初始化,无法自动装配

  • 作用范围 成员变量\构造器\set 方法\构造器入参\非静态方法入参
    基于变量依赖注入使用最广泛,但是缺点 :
    无法在启动时对注入的属性进行安检:
    1. 只有业务使用时才能拿到类,注入对象的为null,暴露晚
    2. 配置信息错误,测试执行阶段才知道
    别的类想重新设置下你的某个注入属性,没法处理(当然反射可以做到).

    spring 推荐 基于构造函数和基于setter的依赖注入.: ( 小白视角: 写的很冗余,用字段方便简洁多了)
      基于构造函数的注入 : 对必需的依赖项以使它们成为不可变的,并防止它们为null。
      对于可选的依赖项,建议使用基于Setter的注入
    

                              1 成员变量在成员变量上使用Autowired注解:
                              @Service
                              public class UserService {

                                  @Autowired
                                  private IUser user;
                              }这种方式可能是平时用得最多的。4.2 构造器在构造器上使用Autowired注解:@Service
                              public class UserService {

                                  private IUser user;

                                  @Autowired
                                  public UserService(IUser user) {
                                      this.user = user;
                                      System.out.println("user:" + user);
                                  }
                              }注意,在构造器上加Autowired注解,实际上还是使用了Autowired装配方式,并非构造器装配。4.3 方法在普通方法上加Autowired注解:@Service
                              public class UserService {

                                  @Autowired
                                  public void test(IUser user) {
                                     user.say();
                                  }
                              }spring会在项目启动的过程中,自动调用一次加了@Autowired注解的方法,我们可以在该方法做一些初始化的工作。也可以在setter方法上Autowired注解:
                              @Service
                              public class UserService {

                                  private IUser user;

                                  @Autowired
                                  public void setUser(IUser user) {
                                      this.user = user;
                                  }
                              }4.4 参数可以在构造器的入参上加Autowired注解:@Service
                              public class UserService {

                                  private IUser user;

                                  public UserService(@Autowired IUser user) {
                                      this.user = user;
                                      System.out.println("user:" + user);
                                  }
                              }
                              也可以在非静态方法的入参上加Autowired注解:@Service
                              public class UserService {

                                  public void test(@Autowired IUser user) {
                                     user.say();
                                  }
                              }
                              4.5 用在注解上

                              4.6 自动装配默认都是单个实例
                                  Autowired 实现自动装配多个实例
                                  UserService方法调整一下,用一个List集合接收IUser类型的参数:
                                  @Service
                                  public class UserService {

                                      @Autowired
                                      private List<IUser> userList;

                                      @Autowired
                                      private Set<IUser> userSet;

                                      @Autowired
                                      private Map<String, IUser> userMap;

                                      public void test() {
                                          System.out.println("userList:" + userList);
                                          System.out.println("userSet:" + userSet);
                                          System.out.println("userMap:" + userMap);
                                      }
                                  }增加一个controller:@RequestMapping("/u")
                                  @RestController
                                  public class UController {

                                      @Autowired
                                      private UserService userService;

                                      @RequestMapping("/test")
                                      public String test() {
                                          userService.test();
                                          return "success";
                                      }
                                  }

3.2.2 @Resource
@Resource装配顺序  
1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常  
2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常  
3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常  
4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;推荐使用@Resource注解在字段上,这样就不用写setter方法了.并且这个注解是属于J2EE的,减少了与Spring的耦合,这样代码看起就比较优雅 。

posted @ 2022-03-06 16:07  悠然采  阅读(223)  评论(0编辑  收藏  举报