spring注入的对象和new的对象到底有啥区别

在使用springboot过程中,想使用jdbc模板,就是直接在service层注入一个jdbcTemplate属性,然后直接使用,但是又想封装一下,就创建一个类,类中有jdbcTemplate属性,然后再service中调用我封装的jdbc,刚开始没有封装方法的情况下,想在service中直接想注入我的类,然后调用我的类中的jdbc,什么注解都标注好了,结果一直空指针异常,还以为不好使呢,其实这里面有个很大的问题,就是注解注入的对象和new的对象到底有啥区别;

我们知道,new一个对象的时候,初始化顺序是,父类静态块>子类静态块> 父类属性(先系统默认值,后直接你赋予的值) >父类构造器>子类属性>子类构造器

但是当有个注解在属性上的时候,会是啥情况呢?

 
  1. @Repository

  2. public class A {

  3. /**

  4. * 属性初始化的顺序是在构造器之前,编译器也会先设置默认值,然后赋予指定值

  5. * 但是当该类的实例是spring注解的注入方式,那么被指定的值不会被赋值

  6. */

  7. public int aa=1;//定义到C的前面,会被先于C初始化

  8. public String as;//如果该类的对象是springMVC注解注入的方式,那么这个属性默认是null,即使赋值,也是空

  9. @Resource

  10. public C c ; //不会被初始化 如果 = new C(); 会先于aa和aaa初始化

  11. public int aaa=2;//定义到C的后面,但是 C不会被初始化

  12. public void run(){

  13. System.out.println("aaaaa");

  14. c.foo();

  15. }

  16. }

  17.  
  18. @RestController

  19. public class B {

  20. @Resource

  21. public A a = new A();

  22. @RequestMapping("/B")

  23. public void test1() {

  24.  
  25. System.out.println(a.as);//如果是注解注入A对象,注意此时A的初始化 只是简单的调用A的空构造函数,A中的属性默认都是默认值(int是0,类属性是null),A中的属性如果自定义了赋值,也不会被使用。

  26. System.out.println(a.aa);

  27. //a.c.foo();

  28. System.out.println(a.c);

  29. System.out.println(a.aaa);

  30. }

  31. }

  32.  
  33. @Component

  34. public class C {

  35. public C() {

  36. System.out.println("C..init..");

  37. }

  38. public void foo(){

  39. System.out.println("cccc");

  40. }

  41. }

结论:注入的对象,只会调用空参构造函数,且这个对象的所有属性都是默认值,自己手动赋予的值不会被使用,

所以在A中的C类,在B中调用A的时候,创建的A对象的属性都是默认值,所以A对象虽然有了,但是A的属性C却是null,所以在B中直接this.a.c.method()是会报null指针异常的,且是c是null的发生原因。

解决方式:C在A中添加get方法,然后B中使用a.getC()即可获得c的对象,且c的对象也是spring注入的。

备注:以上结论和说明,只是个人总结,包括new一个对象初始化顺序,可能不严谨,没有时间验证,以后会完善

猜你喜欢

转载自blog.csdn.net/weixin_41167961/article/details/81391136