Spring注解开发(八)——自动装配@Autowired&@Resource&@Inject

目录

@Autowired

@Resource

@Inject


 

@Autowired

自动注入:

  1. 默认优先按照类型去容器中找对应的组件 
    annotationConfigApplicationContext.getBean(PersonDao.class)
  2. 如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
    annotationConfigApplicationContext.getBean("personDao")
  3. 使用@Qualifier指定要注入哪个组件,根据id来,而不是默认的属性名
  4. 自动装配默认一定要将属性赋值好,没有就会报错,可以通过
    @Autowired(required = false) 来解决
  5. @Primary:让spring容器在自动装配的时候,默认首选的bean,也可以继续使用@Qualifier来制定(即@Qualifier 的优先级最高)

实体bean:

package com.cjian.dao;

import org.springframework.stereotype.Repository;

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/10/28 11:25
 */
@Repository
public class PersonDao {

    private String label;

    public PersonDao() {
    }

    public PersonDao(String label) {
        this.label = label;
    }

    @Override
    public String toString() {
        return "PersonDao{" + "label='" + label + '\'' + '}';
    }

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }
}

我们在这里使用@Autowired注入了一个personDao

package com.cjian.service;

import com.cjian.dao.PersonDao;

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

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/10/28 11:25
 */
@Service
public class PersonService {

    @Autowired
    private PersonDao personDao;

    @Override
    public String toString() {
        return "PersonService{" + "personDao=" + personDao + '}';
    }
}

 配置类:

package com.cjian.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/10/28 9:32
 */
@Configuration //告诉spring这是一个配置类
@ComponentScan( {"com.cjian.dao", "com.cjian.service", "com.cjian.controller"})
public class MainConfigAutowired {

   /* @Bean("personDao2")
    public PersonDao personDao() {
        return new PersonDao("2");
    }*/

}

测试代码:

package com.cjian;

import com.cjian.config.MainConfigAutowired;
import com.cjian.dao.PersonDao;
import com.cjian.service.PersonService;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/11/3 11:13
 */
public class TestAutowired {

    static AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(
        MainConfigAutowired.class);

    public static void main(String[] args) {
        String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();

         System.out.println(annotationConfigApplicationContext.getBean(PersonDao.class));
         System.out.println(annotationConfigApplicationContext.getBean("personDao"));
         System.out.println(annotationConfigApplicationContext.getBean(PersonService.class));
    }


}

输出:

PersonDao{label='null'}
PersonDao{label='null'}
PersonService{personDao=PersonDao{label='null'}

证明了默认是按照类型去容器中找对应的组件

测试,如果我们将配置类的注解放开:

@Configuration //告诉spring这是一个配置类
@ComponentScan( {"com.cjian.dao", "com.cjian.service", "com.cjian.controller"})
public class MainConfigAutowired {

    @Bean("personDao2")
    public PersonDao personDao() {
        return new PersonDao("2");
    }

}

再次运行时,会报错:

Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.cjian.dao.PersonDao' available: expected single matching bean but found 2: personDao,personDao2
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1200)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:420)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1127)
	at com.cjian.TestAutowired.main(TestAutowired.java:26)

这时候容器里面有两个personDao的组件,但是也不应该报这个错,报这个错是由于System.out.println(annotationConfigApplicationContext.getBean(PersonDao.class)); 这行代码导致的,它不知道该获取哪个组件,注释该代码后运行如下:

PersonDao{label='null'}
PersonService{personDao=PersonDao{label='null'}}

此时验证了,如果容器中有多个组件,会按照id去查找(persongService里注入的是personDao),即相当于annotationConfigApplicationContext.getBean("personDao");

再来验证下,我们将service里注入的dao的名字改成这样的:

@Service
public class PersonService {

    @Autowired
    private PersonDao personDao2;

    @Override
    public String toString() {
        return "PersonService{" + "personDao=" + personDao2 + '}';
    }
}

输出:

PersonDao{label='null'}
PersonService{personDao=PersonDao{label='2'}}

再次验证如果容器中有多个组件,会按照id去查找,

 

如果这时候,就算我们定义了

private PersonDao personDao2;

但是我们任然想获取personDao咋办呢?

使用@Qualifier注解:

@Service
public class PersonService {

    @Qualifier("personDao")
    @Autowired
    private PersonDao personDao2;

    @Override
    public String toString() {
        return "PersonService{" + "personDao=" + personDao2 + '}';
    }
}

输出:

PersonDao{label='null'}
PersonService{personDao=PersonDao{label='null'}}

验证结束!

使用@Primary来设置默认装备哪个bean:

@Configuration //告诉spring这是一个配置类
@ComponentScan( {"com.cjian.dao", "com.cjian.service", "com.cjian.controller"})
public class MainConfigAutowired {

    @Primary
    @Bean("personDao2")
    public PersonDao personDao() {
        return new PersonDao("2");
    }

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

 @Autowired可以用在构造器,方法,参数,属性上

  1. 标注在方法上:@Bean+方法参数,参数会从容器中获取,默认不写@Autowired
  2. 标注在构造器上,如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还可以自动从容器中获取
  3. 放在参数位置

 

 

@Resource

JSR250 的java规范

可以和@Autowired一样实现自动装配的功能,默认是按照组件名称装配的,不支持@Primary和@Autowired(required=false)的功能

@Service
public class PersonService {

    // @Qualifier("personDao")
    // @Autowired(required = false)
    @Resource
    private PersonDao personDao2;

    @Override
    public String toString() {
        return "PersonService{" + "personDao=" + personDao2 + '}';
    }
}

输出:

PersonDao{label='null'}
PersonService{personDao=PersonDao{label='2'}}
@Service
public class PersonService {

    // @Qualifier("personDao")
    // @Autowired(required = false)
    @Resource(name="personDao")
    private PersonDao personDao2;

    @Override
    public String toString() {
        return "PersonService{" + "personDao=" + personDao2 + '}';
    }
}

输出:

PersonDao{label='null'}
PersonService{personDao=PersonDao{label='null'}}

 

@Inject

也是JSR250的java规范

和@Autowired功能一样,但是不支持@Autowired(required=false)的功能

需要导入依赖:

<!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>
@Service
public class PersonService {

    // @Qualifier("personDao")
    // @Autowired(required = false)
    //@Resource(name="personDao")
    @Inject
    private PersonDao personDao2;

    @Override
    public String toString() {
        return "PersonService{" + "personDao=" + personDao2 + '}';
    }
}

输出:

PersonDao{label='null'}
PersonService{personDao=PersonDao{label='2'}}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值