美文网首页
springboot中依赖对象实例化问题

springboot中依赖对象实例化问题

作者: Java编程日记 | 来源:发表于2022-03-25 19:11 被阅读0次

一个问题,暴露出不少问题。然后解决这些问题。

一、问题描述

有个SpringBoot项目,启动的时候,读取某对象的属性报错,因为该对象为null。

这个对象使用了@Autowired注解,看上去,是对象实例化的顺序问题。即A里面使用了B,B由容器负责实例化,但A使用B的时候,B却还没来得及注入。

二、问题解决

1、A等B实例化之后再使用B

使用@PostConstruct注解,比如:

@Service
public class AImpl implements A {

    @Autowired
    B config;

    @PostConstruct
    void init(){

        if(config.isDebug){

            System.err.println("开启调试模式。。。");
        }
    }
}

注解@PostConstruct 的作用是,所有依赖的对象都实例化以后,自动执行本方法。上面例子中,当对象config实例化以后,系统将自动执行init()方法。注意加上 @PostConstruct注解 的方法,是系统自动执行,无须显式调用。并且这个方法不能带有参数。

对比一下改写之间的代码:

@Service
public class AImpl implements A {

    @Autowired
    B config;

    public AImpl(){

        init();
    }

    void init(){

        if(config.isDebug){
 //报错,因为config == null
            System.err.println("开启调试模式。。。");
        }
    }
}

2、普通类使用静态方法使用B

普通类是不能直接使用 @Autowired注解 的。如果一个类想让它的属性使用@Autowired注解,那么它本身也应该由容器实例化,即类本身也要加上@Component 、@configration、@service、@Controller等注解。普通类的属性加上@Autowired,能编译,能运行,但永远都是null。

那如果普通类想使用这个由容器注入的对象,咋办呢?我在上面提到的项目中,采用静态方法获取该对象的方式,核心还是这个@PostConstruct注解。具体如下:

@Component
public class B {

    private static B config = null;

    private boolean debug;
    public boolean isDebug() {

        return debug;
    }
    public void setDebug(boolean debug) {

        this.debug = debug;
    }

    @PostConstruct
    void init() {

        config = this;
    }

    public static B getInstance() {

        if (config == null) {
 //纯粹防御一下,不写这句应该也可以
            config = new B();
        }
        return config;
    }
}

public class C {

    public void run(){

        if(B.getInstance().isDebug()){

            System.err.println("俺也开启调试模式。。。");
        }
    }
}

三、相关知识点

1、IoC容器

Spring的核心就是所谓的IoC容器。这个IoC容器主要负责实例化对象,或者说,是提供Bean的地方。IoC,控制反转。何谓控制反转?就是对象创建的控制权转移了。原本构造对象实例,都是我们在代码中,显式地new。而在Spring中,这些工作都由容器来完成,控制权转给了容器。容器根据类(Bean)的定义,结合Bean的实现类,构造出Bean实例。像我们代码中,

@Autowired
    B config;

B的实例config,就由容器负责实现。

springboot中依赖对象实例化问题 springboot中依赖对象实例化问题 springboot中依赖对象实例化问题

IoC容器的意义

1)方便编码,提升开发效率

2)可以应对复杂的项目开发

类与类之间的依赖,如果数量少还好,很多的话,依赖关系非常复杂,不容易理清

springboot中依赖对象实例化问题

3)修改比较容易,提高系统可修改性

IoC本质上是面向接口编程,在我们代码中,声明的是接口对象,由容器根据实现类进行注入,因此声明与实现是解耦的。万一需要切换实现类,那么修改的地方就少了许多。

4)节省资源

Spring中的bean默认都是单例的。当然也会有每次都创建一个新实例的情况,本人暂时还不是很清楚其中的细节。先记录下来:

springboot中依赖对象实例化问题

容器容器,可以看做黑箱,装的是Bean实例,系统启动之初就自动生成,直接使用即可,犹如探囊取物,煞是方便。

2、@Component , @Repository , @ Controller , @Service , @Configration

都是Bean的注解,不同类型。

从广义上Spring注解可以分为两类:

1)一类是注册Bean,像@Component , @Repository , @ Controller , @Service , @Configration

这些注解就是用于注册Bean,由IoC容器在系统启动之初注入并任君取用。

2)一类是使用Bean,比如@Autowired , @Resource。

3、@Bean

上面说到,@Component , @Repository , @ Controller , @Service , @Configration都是Bean的注解,但SpringBoot也有一个@Bean注解。

@Component , @Repository , @ Controller , @Service , @Configration是类注解,用在类头;@Bean是方法注解,用在类的方法里(当然啦,类头也要添加@Component、@Service之类的注解才能起作用)。

为什么要有这么个注解呢?原来,@Component , @Repository , @ Controller , @Service , @Configration针对的是本项目中的类,如果引用第三方类,又想让它交由IoC管理怎么办?这时就可以用@Bean。

相关文章

  • springboot中依赖对象实例化问题

    一个问题,暴露出不少问题。然后解决这些问题。 一、问题描述 有个SpringBoot项目,启动的时候,读取某对象的...

  • 05--SpringBoot启动之事件监听机制

    之前的文章分析了SpringBoot如何实例化SpringApplication对象,接下来分析run方法中的事件...

  • 2018-10-16

    redis集群配置 1、springboot中加入依赖: //====== redis 采用gson序列化对象==...

  • 循环依赖问题

    问题描述 有多个对象,A依赖B,B依赖A。导致实例化的时候会进入死循环导致内存溢出。 三种循环依赖 1.构造器的循...

  • Spring中BeanFactory和FactoryBean的区

    BeanFactory就是一个Bean工厂,负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。 Bea...

  • angular4 (2)依赖注入

    如果一个对象A需要依赖对象B,那么对象A不需要明确实例化对象B,B会由外部机制注入进来。 <1>提供器声明在模块中...

  • Springboot 天气api开发

    从天气项目开始 标签: springboot api 天气接口 接口 接口案例 逻辑实现:实例化返回对象,通过配置...

  • 静态内部类和非静态内部类的区别

    嵌套类的对象,并不需要其外围类的对象。 即它可以不依赖于外部类实例被实例化。 不能从嵌套类的对象中访问非静态的外围...

  • python类共享变量详解

    问题: python类对象A,先实例化一个A对象的实例b,接着给A对象添加一个类共享变量xxx,再实例化一个c,请...

  • 03-this的指向--js

    1.this在构造函数中 指向 实例对象 new 的过程 -- 实例化 被创建出来的对象 -- 实例对象 ...

网友评论

      本文标题:springboot中依赖对象实例化问题

      本文链接:https://www.haomeiwen.com/subject/yppdjrtx.html