ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring注解之@Autowired:装配构造函数和属性

2020-07-11 15:04:22  阅读:382  来源: 互联网

标签:Autowired Spring public bean student import id 构造函数


       在User类中创建一个构造函数,传入参数student:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.Serializable;

/**
 * @author Wiener
 */
@Component
public class User implements Serializable {
    private static final long serialVersionUID = 6089103683553156328L;
    private Long id;

    private Student student;

    public Long getId() {
        return id;
    }

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

    @Autowired  // 构造函数注入参数的方式
    User(Student student) {
        this.student = student;
        System.out.println("------ 为构造器装配Bean成功 ---------");
    }
    public void isStu() {
        student.studentStudy();
        System.out.println("------ 装配Bean成功 ---------");
    }
}

       其中,Student类如下:

import lombok.Getter;
import lombok.Setter;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Date;

/**
 * @author Wiener
 */
@Getter
@Setter
@Component
public class Student implements Serializable {

    private static final long serialVersionUID = -5246589941647210011L;

    //姓名
    private String name;
  
    public Student() {
        System.out.println("A default student constructor." );
    }
    public void studentStudy() {
        System.out.println("A student is studying." );
    }
}

改造Spring Boot项目启动类:

import com.east7.bean.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

/**
 * @author Wiener
 */
@SpringBootApplication
public class East7Application {

    public static void main(String[] args) {
       ApplicationContext act = SpringApplication.run(East7Application.class, args);
        User user = (User) act.getBean("user");
        user.isStu();
    }

}

执行测试函数后,控制台打印信息如下:

A default student constructor.
------ 为构造器装配Bean成功 ---------
A student is studying.
------ 装配Bean成功 ---------

       说明成员变量已经注入。此处需要注意一点,如果有两个自定义构造方法,而且都没加@Autowired注解,则会报错,因为Spring不知道你要用哪个构造方法初始化;如果只有一个构造方法加了@Autowired注解,那么就会用这个构造方法初始化;同理,如果有多个构造方法都加了@Autowired注解,那么还是会报错提示Only one constructor can have @Autowired annotation。

       可以在属性中使用@Autowired 注解来省略 setter 方法。当使用@Autowired为自动连接属性传递的时候,Spring 会将这些传递过来的值或者引用自动分配给那些属性。像下面这样写在属性上并直接引用会报空指针异常:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* @author Wiener
*/
@Component
public class User {

    @Autowired //变量注入方式
    private Student student;
    private Long id = student.getId();

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public void isStu() {
        id = student.getId();
        student.studentStudy();
        System.out.println("------ 装配Bean成功 ---------");
    }
}

异常信息如下:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'user' defined in file [xxxxxx\User.class]: 
Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [com.east7.bean.User]:
Constructor threw exception; nested exception is java.lang.NullPointerException

报错信息提示创建Bean时出错,因为实例化bean时构造方法抛出了空指针异常。如果仅仅使用函数isStu()初始化变量id, 并且把【private Long id = student.getId();】改为 【private Long id;】,则属于方法调用的时候初始化,此时,bean已经注入,不会抛异常。 

       其实这两种方式都可以使用,但报错的原因是加载顺序的问题,@autowired写在变量上的注入要等到类完全加载后,才会将相应的bean注入,而变量是在加载类的时候按照相应顺序加载的,所以变量的加载要早于被@autowired注解的变量,那么给变量prefix 赋值的时候所使用的a,其实还没有被注入,所以报空指针,而使用构造器则会在加载类的时候将a加载,这样在内部使用a给prefix 赋值就完全没有问题。 

       如果不使用构造器,那么也可以不给prefix 提前赋值,而是在系统启动后,变量prefix被使用的地方,通过a.getExcelPrefix()进行赋值,此时对a的使用是在类完全加载之后,即a被注入后,所以也是可以的。 

       总之,@Autowired一定要等本类构造完成后,才能从外部引用设置属性,所以@Autowired的注入时间一定会晚于构造函数的执行时间。但在初始化变量的时候就使用了还没注入的bean,所以导致了NPE。若在初始化其它变量时不使用这个要注入的bean,而是在后期调用方法的时候去初始化,是可以使用这个bean的,因为那时构造函数已经执行完毕,即已注入bean了。一言以蔽之,Java变量的初始化顺序为:静态变量或静态语句块–>实例变量或初始化语句块–>构造函数–>@Autowired 注入Bean

 

标签:Autowired,Spring,public,bean,student,import,id,构造函数
来源: https://www.cnblogs.com/east7/p/13283586.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有