new与@Autowrite创建对象的区别

问题

今天在工作的时候遇到一个问题,在项目接入的MagicApi模块中添加一个接口在,创建数据源的时候自动创建两个查询接口一个是带分页的一个是不带分页的。

当时这个方法创建这两个接口会给他分配一个分组,如果该分组不存在,则magicApi中也不会有这两个接口,但是源码中写的是死分组ID,并且是UUID类型的,无法确定是那一个分组

找到创建接口的函数,发现调用了一个工具类来创建,接口,当时的想法是直接在工具类中,实现一个方法,将默认分组名和分组路径写入到SpringBoot的配置文件中,这也方便修改。

我当时想直接在工具类中创建这样一个方法,但是工具类没有使用SpringBoot的组件注解,所以我才用了new一个Springboot中的Service层对象来实现该方法,该Service层实现了Mybatis-Plus的一系列接口。

在使用数据库查询语句的时候,发现,lambdaQueryMapper写的一点问题没有,但是使用mybatis-Plus中的list方法的时候缺报空指针异常,百思不得其解。

分析

查阅得知

  • 使用new关键字创建的对象是一个普通的Java对象不会获得Spring框架提供的任何依赖注入或生命周期管理服务
  • 使用@Autowired注解注入的对象是Spring框架管理的bean,它会获得所有必要的依赖注入,并能够使用Spring框架提供的各种服务

使用new关键字创建对象

当你使用new关键字来创建一个对象时,这个对象的创建和管理完全是在你的代码控制之下,不涉及到Spring框架的依赖注入或生命周期管理。因此,这个对象只是一个普通的Java对象,它不会自动地获得Spring容器管理的任何依赖项或服务

myService对象继承自Mybatis-Plus的IService接口,但是如果直接通过new来创建这个对象,那么这个对象将不包含Mybatis-Plus或Spring框架为它提供的任何额外功能或服务。特别是,它不会自动地注入与数据库交互所需的Mybatis Mapper或者相关的依赖项,因此你将无法调用如list()这样的方法,因为这些方法可能依赖于Spring容器管理的其他bean或资源。

使用@Autowired注解注入对象

使用@Autowired注解来注入一个对象时Spring框架会负责这个对象的创建、配置和依赖注入。在Spring容器启动时,它会扫描应用程序,找到所有标有@Component@Service@Repository等注解的类,并将它们实例化,然后注入到标有@Autowired注解的字段或方法参数中。

在这个过程中,Spring框架会确保所有必要的依赖项都被正确地注入到被注入的对象中。因此,当你通过@Autowired注入myService对象时,Spring框架会确保所有必要的依赖项(如Mybatis Mapper)都被注入到myService中,这样就可以使用Mybatis-Plus提供的list()等方法了。

Spring控制资源获取方式

  • 主动式: new 一个对象,要什么资源就自己创建即可
  • 被动式:资源的获取不是自己创建,而是交给一个容器来创建

容器:管理所有的spring bean(有功能的类);假设,上面例子中 Test 受容器管理, Test_2 也受容器管理;容器可以自动的探查出那些组件(类)需要用到另一写组件(类);容器帮我们创建 Test 对象,并把 Test_2 对象赋值过去。主动的获取资源变为被动的获取资源,即控制反转(IOC)

Dl:( Dependency Injection):依赖注入器能知道哪个组件(类)运行的时候,需要另外一个类(组件);容器通过反射的形式,将容器中准备好的 Test_2 对象注入(利用反射给属性赋值)到 容器中的Test 对象(注意,此处是容器中的该Test对象,通过new出来的Test对象,容器是无法去进行管理的,new 出来的 Test对象想去容器中主动拉取Test_2对象是不可以的。这样就可以解释上面例子的现象了)

小结:需要被容器管理的类都会在ioc容器中登记,告诉spring你是什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其它需要你的东西。应该ioc容器的管理有点类似于网络通讯吧,你只有登记了获得一个ip地址你才能上网获取东西,或者其它东西获取你。因为对象是被动接受ioc容器的依赖注入的,不是对象主动从ioc容器中拉去依赖对象的。