IoC控制反转和DI依赖注入

Spring容器创建对象的两种方式

一、自己创建的类(可以添加注解)

1、创建实体类Student(添加注解@Component)

@Component
//@Scope("prototype")
//singleton:单例作用域,SPring容器中该类型的对象只有一个,无论获取多少次
//优点:节省内存,缺点:不能做到个性化属性的赋值或修改
//prototype:原型作用域:Spring容器中该类型的对象每获取一次,就会创建一个 新的对象返回
//优点:能做到个性化属性的赋值或修改,缺点:占用内存过多
public class Student {
    private Integer id;
    private String username;
    private String gender;

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}

@Scope(“prototype”) singleton:单例作用域,SPring容器中该类型的对象只有一个,无论获取多少次
优点:节省内存,缺点:不能做到个性化属性的赋值或修改 prototype:原型作用域:Spring容器中该类型的对象每获取一次,就会创建一个
新的对象返回 优点:能做到个性化属性的赋值或修改,缺点:占用内存过多

2、创建配置类(@Configuration和@ComponentScan(“Student所在的包路径”))

//表是当前类是配置Spring框架信息的
@Configuration
//指定组件扫描的包(当前包及其子包的所有类都会被扫描)
//如果被扫描的 类上有四大注解,那么这个类就会被实例化并保存到Spring容器
@ComponentScan("com.example.educationtest.demo")
public class StuConfig {
}

3、在测试类中初始化Spring容器并创建对象


    @Test
    void stuTest(){
        AnnotationConfigApplicationContext acac =
                new AnnotationConfigApplicationContext(StuConfig.class);
        Student zhangsan = acac.getBean("student", Student.class);
        zhangsan.setId(1);
        zhangsan.setUsername("zhangsan");
        zhangsan.setGender("男");
        System.out.println(zhangsan);
    }

二、实体类上不含有注解的(系统的、非自己定义的类)

1、创建实体类Teacher(没有@Component)

public class Teacher {
    private Integer id;
    private String username;
    private String gender;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }
}

2、创建配置类(@Configuration)
在配置类中通过@Bean注解实例化对象

@Configuration
public class TchConfig {
    @Bean
    public Teacher teacher(){
        Teacher tc1 = new Teacher();
        tc1.setId(2);
        tc1.setUsername("少珩");
        tc1.setGender("男");
        return tc1;
    }
    @Bean
    public Date date(){
        return new Date();
    }
}

3、初始化Spring容器

 @Test
    void tchTest(){
       AnnotationConfigApplicationContext acac =
               new AnnotationConfigApplicationContext(TchConfig.class);
        Teacher tc = acac.getBean("teacher", Teacher.class);
        Date  date = acac.getBean("date", Date.class);
        System.out.println(tc);
        System.out.println(date);
    }

总结:仅自定义的类可以使用组件扫描的方式,当然自定义的类型也可以使用@Bean方法的做法,但是不推荐;
非自定义的类型不可以使用组件扫描的方式(因为你没有办法在这些类型上添加注解)只能使用@Bean方法的做法
控制反转:对象的创建和管理交给Spring容器

DI依赖注入

依赖注入:能够直接从Spring中获得拼装好的复杂对象的功能
依赖注入的两种形式

一:当类可以被注解修饰时

1、创建关羽类和青龙偃月刀类(两个类均被注解修饰)

@Component
public class GuanYu {
    String name =  "关羽";
    //自动装配:默认按照类型装配
    @Qualifier("dragonBlade")
    @Autowired
//private DragonBlade dragonBlade;
    private Weapon weapon;

    public Weapon getWeapon() {
        return weapon;
    }

    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }

    public String getName() {
        return name;
    }

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


    public void fight(){
        System.out.println(name+"拿着"+weapon+"去战斗");
    }
}

@Component
public class DragonBlade implements Weapon{
    String name = "青龙偃月刀";

    @Override
    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return name;
    }
}

2、关羽类依赖青龙偃月刀采用@Autowired将青龙偃月刀自动装配给关羽
3、测试类中只需获取关羽,即可调用青龙偃月刀

@Test
    void guanTest2(){
        AnnotationConfigApplicationContext acac =
                new AnnotationConfigApplicationContext(OuConfig.class);
        GuanYu guanYu = acac.getBean("guanYu", GuanYu.class);
        guanYu.fight();
    }

二、当类中没有被注解修饰时

1.创建张飞和丈八蛇矛类

public class ZhangFei {
    private String name = "张飞";
    @Autowired
    @Qualifier("snakeLance")
    private SnakeLance snakeLance;

    public String getName() {
        return name;
    }

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

    public SnakeLance getSnakeLance() {
        return snakeLance;
    }

    public void setSnakeLance(SnakeLance snakeLance) {
        this.snakeLance = snakeLance;
    }
    public void fight(){
        System.out.println(name+"拿着"+snakeLance+"去战斗");
    }
}

public class SnakeLance implements Weapon{
    private String name = "丈八蛇矛";

    @Override
    public String toString() {
        return name;
    }

    @Override
    public String getName() {
        return name;
    }

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

2.创建配置类

@Configuration
@ComponentScan("com.example.educationtest.demo")
public class ZhangConfig {
    @Bean
    public  SnakeLance snakeLance(){
        return new SnakeLance();
    }
    @Bean
    public  SnakeLance snakeLance2(){
        return new SnakeLance();
    }
    //@Bean标记的方法的参数列表如果声明了参数,Spring就会自动从SPring容器中寻找合适的对象,为这个参数赋值
    //也就是说上面保存在容器中的snakelance对象就会自动赋值给参数sl,方法中又将sl赋值给zhangfei属性,所以实现了依赖注入

//    @Bean
//    public ZhangFei zhangFei(SnakeLance snakeLance){
//        ZhangFei zhangFei = new ZhangFei();
//        zhangFei.setSnakeLance(snakeLance);
//        return zhangFei;
//    }

}

3.在测试类中进行测试

    @Test
    void feiTest1(){
        AnnotationConfigApplicationContext acac =
                new AnnotationConfigApplicationContext(ZhangConfig.class);
        ZhangFei zhangFei = acac.getBean("zhangFei", ZhangFei.class);
        zhangFei.fight();
    }

三、解耦

实现解耦的思路:
创建接口,炳然被依赖的类实现接口,即注入由之前具体类型修改为抽象类型,实现解耦
运行时会自动从spring容器中寻找接口类型对象来注入依赖,更换对象时只需更换保存在spring容器中的对象即可
1、创建接口

public interface Weapon {
    String getName();

}
``
2`类中注入时发生的变化

![在这里插入图片描述](https://img-blog.csdnimg.cn/2d71a421414f446983e37a413f0efd76.png)
@Qulifier(“Bean对象”)当有对个Bean对象时指定唯一的一个作为注入的对象
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值