在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

Spring注解之@Autowired:装配构造函数和属性的更多相关文章

  1. Spring注解之@Autowired、@Qualifier、@Resource、@Value

    前言 @Autowired.@Qualifier.@Resource.@Value四个注解都是用于注入数据的,他们的作用就和在xml配置文件中的bean标签中写一个标签的作用是一样的!本篇中特别要讲解 ...

  2. Spring注解之@Autowired

    前言 说起Spring的@Autowired注解,想必大家已经熟悉的不能再熟悉了.本文就针对此最常用的注解,梳理一下它的功能和原理,争取从源码的角度将此注解讲通,如有写的不准确的地方,欢迎各位园友拍砖 ...

  3. Spring 学习——Spring注解——Autowiring(自动装配)

    装配方式 方式一:默认 方式二:byName:根据属性名称自动装配.会查找Bean容器内部所有初始化的与属性名成相同的Bean,自动装配.(需要通过set方法注入,注入Bean的id名称需要和实体类的 ...

  4. Spring 注解实体类中非数据库字段属性

    解决办法:在属性的get方法上加上一段注解标识它是临时属性,不是数据库字段就OK @Transient public List<Reverts> getChildList() { retu ...

  5. spring 注解@Resource @Autowired区别

    1.@Autowired寻找类的时候默认是ByType,也就是通过类的类型来寻找类.不过,也可以通过借助@Qualifier("name")来指定寻找的类名 @Autowired ...

  6. Annotation(三)——Spring注解开发

    Spring框架的核心功能IoC(Inversion of Control),也就是通过Spring容器进行对象的管理,以及对象之间组合关系的映射.通常情况下我们会在xml配置文件中进行action, ...

  7. Spring注解开发系列专栏

    这个系列主要是讲Spring注解的使用,可以为后面SpringBoot的学习带来一定的帮助.我觉得从Spring直接过度到SpringBoot还是有点快,还是得需要一个演变的过程.从Spring开发, ...

  8. Spring中@Autowired注解与自动装配

    1 使用配置文件的方法来完成自动装配我们编写spring 框架的代码时候.一直遵循是这样一个规则:所有在spring中注入的bean 都建议定义成私有的域变量.并且要配套写上 get 和 set方法. ...

  9. Spring AOP注解通过@Autowired,@Resource,@Qualifier,@PostConstruct,@PreDestroy注入属性的配置文件详解

    本文介绍了使用Spring注解注入属性的方法.使用注解以前,注入属性通过类以及配置文件来实现.现在,注入属性可以通过引入@Autowired注解,或者@Resource,@Qualifier,@Pos ...

  10. Spring AOP注解通过@Autowired,@Resource,@Qualifier,@PostConstruct,@PreDestroy注入属性的

    本文介绍了使用spring注解注入属性的方法. 使用注解以前,注入属性通过类以及配置文件来实现.现在,注入属性可以通过引入@Autowired注解,或者@Resource,@Qualifier,@Po ...

随机推荐

  1. 终于写完轮子一部分:tcp代理 了,记录一下

    24年终自己立了flag: 25年做些轮子玩(用于浪费生命,赚不了钱) 所以25年就准备用c#写一个网络代理NZOrz(nginx知道吧,就那玩意儿干的事),包含 udp/tcp/http1 2 3, ...

  2. Abaqus压电材料分析

    目录 1. ABAQUS压电材料定义[快速版] 2. 压电材料的主要特性参数 3. Abaqus 压电分析 1 电响应 2 initial condition & BCs 4 Load 5 M ...

  3. allure 报告环境搭建

    1.安装 pip install allure-pytest 2.下载allure 地址: https://repo.maven.apache.org/maven2/io/qameta/allure/ ...

  4. nginx 配置go服务反向代理

    nginx 配置 详细请看Nginx 极简教程 server { listen 80; server_name localhost; #charset koi8-r; # nginx访问活动日志 ac ...

  5. vue学习一(指令2.v-bind,v-model)

    2.1.v-bind:  单向绑定(修改数据项,标签内容也改变:修改标签内容,数据项不会改变) 给html标签的属性绑定,可以用来动态修改class,简写    v-bind:style    =   ...

  6. 变异凯撒-python脚本调整ascii码转字符串

    题目: 加密密文:afZ_r9VYfScOeO_UL^RWUc 格式:flag{ } 结合题目变异凯撒,第一个字符a到f加了5,第二个字符f到l加了6,推断每个字符都在前一个字符基础上+1. 编写py ...

  7. Linux之SELinux的开启、关闭。

    SELinux简介 SELinux 是Security-Enhanced Linux的简写,意指安全增强的linux.它不是用来防火墙设置的.但它对Linux系统的安全很有用.Linux内核(Kern ...

  8. wait、notify、notifyAll的理解与使用

    基础知识 Java 中,可以通过配合调用 Object 对象的 wait() 方法和 notify() 方法或 notifyAll() 方法来实现线程间的通信. 在线程中调用 wait() 方法,将阻 ...

  9. "油猴脚本""篡改猴"领域的一些基本常识

    本文简要介绍本人对"油猴脚本","篡改猴"领域的一些见解,内容注定不可能一步到位和事无巨细,欢迎各位仁人志士对我批评指正,提出意见建议.另外转载前请务必注明作者 ...

  10. Anonymous打靶学习笔记(5)

    参考视频https://www.bilibili.com/video/BV1XufaYAEKc/?spm_id_from=333.1387.search.video_card.click 常见的100 ...