Spring-03-注入组件使用

chapter08:@Value赋值

新建chapter08目录:
1,新建Brid.java类

public class Bird {
    private String name;
    private int age;
    private String color;

    public Bird() {
    }

    public Bird(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Bird{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", color='" + color + '\'' +
                '}';
    }
}

2,新建Chapter08MainConfig.java配置类

@Configuration
public class Chapter08MainConfig {

    @Bean
   public Bird bird(){
       return new Bird();
   }

}

3,新建测试用例Chapter08MainTest.java, 从容器获取bean并打印。

public class Chapter08MainTest {

    @Test
    public void test(){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Chapter08MainConfig.class);
        // 从容器中获取所有的bean
        String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
        Bird bird = (Bird) ctx.getBean("bird");
        System.out.println(bird);
        ctx.close();
    }
}

打印结果:
在这里插入图片描述
4,使用@Value赋值如何赋值呢?见下
在这里插入图片描述
输出:
在这里插入图片描述

5,从配置文件[properties]读取, 新建test.properties
在这里插入图片描述
6,在Bird类的color字段添加@Value
在这里插入图片描述
7,将test.properties配置文件加载起来。
在这里插入图片描述
8,再次运行结果是:
在这里插入图片描述
9,test.properties值是加在运行环境变量里
在这里插入图片描述
输出:
在这里插入图片描述

chapter09:@Autowired自动装配

自动装配:spring利用依赖注入(DI), 完成对IOC容器中的各个组件的依赖关系赋值

1,新建TestController.java TestService.java TestDao; 分别建在指定的包内,可看步骤2
这些所有JAVA 类的对象扫描后都是保存在IOC容器中管理的。

@Repository
public class TestDao {

}

@Service
public class TestService {
    @Autowired
    private TestDao testDao;
    //testDao打印出来(在测试时方便对比)
    public void println(){
        System.out.println(testDao);
    }

}

@Controller
public class TestController {
    @Autowired
    private TestService service;
}

2,新建配置类Chapter09MainConfig .java,扫描并将以上bean都扫描并加载到容器。

@Configuration
@ComponentScan("com.bruce.chapter09")
public class Chapter09MainConfig {
}

3, 新建Cap9Test.java测试用例,比较TestService拿到testDao与直接从容器中拿到的testDao是否为同一个?

public class Chapter09MainTest {

    @Test
    public void test(){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Chapter09MainConfig.class);
        TestService bean = ctx.getBean(TestService.class);
        bean.println();
        //直接从容器中获取TestDao和使用@Autowired注解来取比较
        TestDao bean1 = ctx.getBean(TestDao.class);
        System.out.println(bean1);
        ctx.close();
    }
}

输出:
在这里插入图片描述
小结:
@Autowired表示默认优先按类型去容器中找对应的组件,相当于anno.getBean(TestDao.class)去容器获取id为testDao的bean, 并注入到TestService的bean中。

4,注意事项
4.1,如果容器中找到多个testDao, 会加载哪个testDao呢?
操作步骤:
将TestDao加入flag属性和set, get及toString方法,用来分辨加载了哪个bean。

@Repository
public class TestDao {
    //默认是1
    private int flag = 1;
    public TestDao(){

    }
    public TestDao(int flag) {
        this.flag = flag;
    }

    public int getFlag() {
        return flag;
    }

    public void setFlag(int flag) {
        this.flag = flag;
    }

    @Override
    public String toString() {
        return "TestDao{" +
                "flag=" + flag +
                '}';
    }
}

并将在Chapter09MainConfig .java声明@Bean(“testDao”)

@Configuration
@ComponentScan("com.bruce.chapter09")
public class Chapter09MainConfig {
    //若TestService获取的testDao是这个bean,应打印出flag为2
    @Bean("testDao")
    public TestDao testDao(){
        return new TestDao(2);
    }
}

输出:
在这里插入图片描述
说明容器放入的是@Bean标注的testDao,而不是@Repository本身标注的testDao。说明@Bean标注的bean优先级高于@Repository标注的。

4.2, 将在Chapter09MainConfig .java声明@Bean(“testDao2”)

@Configuration
@ComponentScan("com.bruce.chapter09")
public class Chapter09MainConfig {
    //若TestService获取的testDao是这个bean,应打印出flag为2
    @Bean("testDao2")
    public TestDao testDao(){
        return new TestDao(2);
    }
}

修改测试类:
在这里插入图片描述

相当于往容器中注册了bean的id为testDao2的TestDao bean,输出TestDao类型的bean有哪些。
在这里插入图片描述
4,3,当有多个同类型的bean的时候,可以根据bean的id来获取不同的bean。
在这里插入图片描述
输出:
在这里插入图片描述
修改方法中的id:
在这里插入图片描述
输出:
在这里插入图片描述
4.4,虽然以上定义了private TestDao testDao2, 但还是想加载bean id为testDao(flag=1)的bean,怎么办?此时可以使用@Autowired和@Qualifier结合来指定注入哪一个bean。
在这里插入图片描述
输出:
在这里插入图片描述
4.5,如果容器中没有任何一个testDao, 会出现什么状况呢?
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
很明显报错了, 因为@Autowired注解里的属性默认required=true必须找到bean。
那怎么解决呢?
在这里插入图片描述
输出:
在这里插入图片描述
4.6,@Primary注解指定bean如何加载呢?
以上原注释掉的@Repository和@Bean(“testDao2”) 恢复。
重要:
为了验证@Qualifier与@Primary两注解的加载顺序,测试如下。
在这里插入图片描述
在这里插入图片描述
修改测试类:

public class Chapter09MainTest {

    @Test
    public void test(){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Chapter09MainConfig.class);
        TestService bean = ctx.getBean(TestService.class);
        bean.println();
        //直接从容器中获取TestDao和使用@Autowired注解来取比较
        TestDao bean1 = ctx.getBean(TestDao.class);
        System.out.println("getbean........testDao....." + bean1);
    
        String[] beanNamesForType = ctx.getBeanNamesForType(TestDao.class);
        for (String s : beanNamesForType) {
            System.out.println(s);
        }
        ctx.close();
    }
}

输出:
在这里插入图片描述

TestService…testDao…TestDao{flag=1}:TestService打印的结果:使用了@Qualifier,表示直接到容器中找寻testDao的bean,flag= 1。
getbean…testDao…TestDao{flag=2}:直接使用ctx.getBean(TestDao.class),获取到的是@Primary注解声明的bean,flag = 2。

4,7,此时只能说明一点: @Qualifier是根据bean id指定获取testDao, 不受@Primary影响.
那么@Primary的功能在哪呢?继续测试…
在这里插入图片描述
输出:
在这里插入图片描述
很明显都是注入@Primary指定的testDao,通过@Primary标记的bean,它的bean默认被首选使用。

注意:
如果注销掉@Primary,再通过ctx.getBean(TestDao.class)获取会报错,因为存在两个类型为TestDao的bean,没有默认选择哪个,就会报错。

4.8,除了@Autowired, 是不是还用过@Resource(JSR250) 和@Inject(JSR330) 。

将Qualifier和Autowired注释掉(注意: 此时@Primary 还没注释…)
在这里插入图片描述
测试结果:
在这里插入图片描述
效果也是一样的, 但它不先优先装配@Primary的bean。
小结:
@Resource和Autowired的区别如下:
@Resource和Autowired一样可以装配bean
@Resource缺点: 不能支持@Primary功能
不能支持@Autowired(required = false)的功能

4.9, @Inject自动装配的使用
注:@Inject与@Autowired的区别如下:
@Inject和Autowired一样可以装配bean, 并支持@Primary功能, 可用于非spring框架.
@Inject缺点: 但不能支持@Autowired(required = false)的功能,需要引入第三方包javax.inject
操作步骤:
1,pom.xml导入javax.inject包

		<dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>

2,使用@Inject注解
在这里插入图片描述
输出:
在这里插入图片描述
结论:@Inject不支持required=false, 但支持primary。
在这里插入图片描述
总结:
Autowired属于spring的, 不能脱离spring, @Resource和@Inject都是JAVA规范
推荐大家使用@Autowired。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值