Spring的三种基本注入方式
同篇发布:Spring是如何注入的?
前言:Spring是什么?
用几句白话聊聊Spring两大特性
IOC(控制反转):
- 控制反转:将你所控制的对象交给“程序”托管。
- 作用:减少你你创建对象时手动书写new的过程。
- 原理:它将你所托管的类实例化到一个“大缸”里,在你使用时直接“取出”即可。
- 简而言之:如果你要使用某个类:开箱即用。
AOP(切面):
- 切面:形如“小三”,半路插上一脚,整个过程相当于第三方“介入”到原有的程序中。
- 作用:以“第三人称”的方式遍布全局作为事务/日志/监控等“介入”程序来达到事务控制/日志记录/安全监控等操作,同时又不会影响到程序本身。
- 原理:在您正确“告知”(配置)程序哪些地方(代码点)需要“介入”(切入)后,程序运行到这些地方,就会在不影响主程序的情况下同时执行第三方“介入”后的操作。
- 抽象白话:假如你上报交通局某个十字路口需要安装红绿灯,当红绿灯安装完成后,就能够正常作为该路段的指示灯来引导交通。
- 本文代码请在您本机可以正常使用Spring的情况下参考使用
属性注入
解析
- 先调用类的空参构造方法创建对象,再调用每个属性的set方法将value作为参数传入,来完成对象实例化
- 注意:1、必须有空参构造方法;2、所注入属性必须有对应set方法
代码层
- 实体类如下
public class Student {
private int sno;
private String sname;
private String major;
private List<String> required;
//省略默认空参构造方法
public void setSno(int sno) {
this.sno = sno;
}
public void setSname(String sname) {
this.sname = sname;
}
public void setMajor(String major) {
this.major = major;
}
public void setRequired(List<String> required) {
this.required = required;
}
//...省略toString()
}
- xml配置如下
<bean name="student" class="Spring.StudentBean.Student">
<property name="sno" value="213"/>
<property name="sname" value="张三"/>
<property name="major" value="计算机科学与技术"/>
<property name="required">
<list>
<value>Java</value>
<value>C++</value>
<value>Android</value>
<value>ASP.NET</value>
</list>
</property>
</bean>
构造器注入
解析
- 调用类的有参数构造方法,按index对应参数位置传入value参数创建对象
- 注意:1、类中必须包含每个constructor-arg标签对应的参数的构造方法
代码层
- 实体类如下
public class Student {
private int sno;
private String sname;
private String major;
private List<String> required;
public Student(int sno, String sname, String major, List<String> required) {
this.sno = sno;
this.sname = sname;
this.major = major;
this.required = required;
}
//...省略toString()
}
- xml配置如下
<bean name="student" class="Spring.StudentBean.Student">
<constructor-arg index="0" value="213"/>
<constructor-arg index="1" value="张三"/>
<constructor-arg index="2" value="计算机科学与技术"/>
<constructor-arg index="3">
<list>
<value>Android</value>
<value>ASP.NET</value>
<value>JavaEE</value>
<value>网络工程</value>
</list>
</constructor-arg>
</bean>
注解注入
解析
-
context:component-scan扫描查找标有构造性注解的类,诸如【@Component(组件),@Service(服务),@Controller(控制器),@Repository(数据仓库)】等注解所标注的类,将其注入到容器中。
-
在注解上如果不指定name,那么程序默认将其类名的首字母小写的名称当做name
-
注意:1、需要在xml配置context:component-scan来扫描我们使用注解注入的类或其多级父包;2、如未在注解上指定name属性,程序自动按照类名的首字母小写名来注入
-
@PropertySource:用于读取数据文件,value设置读取位置,encoding设置读取编码。
-
这里从StudentProperty.properties读取属性,通过@Value将属性拿到并赋值给属性。
-
@Value("${v}"):标记属性,当读取到properties数据后,通过占位符拿取对应值,形如key-value。
代码层
- 实体类如下
@Component
@PropertySource(value = "/Spring/StudentBean/Property/StudentProperty.properties", encoding = "GBK")
public class Student {
@Value("${sno}")
private int sno;
@Value("${sname}")
private String sname;
@Value("${major}")
private String major;
@Value("${required}")
private List<String> required;
//...省略toString()
}
- xml配置如下
<context:component-scan base-package="Spring.StudentBean"></context:component-scan>
- StudentProperty.properties 数据配置文件
sno=213
sname=张三
major=计算机科学与技术
required: JSP, Android, C#, 数据结构
其它建议
-
同时测试三种注入方法可能会引起冲突、属性覆盖等问题,建议使用Junit测试单元分开测试。
-
同时我使用的是maven引入Spring和Junit的jar包,以下参考:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE </version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<!--测试单元-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
- 参考测试代码:
/**
*
* @description: 属性注入测试
* @remarks: 执行原理:(Stu1ApplicationContext)先调用空参的构造方法创建对象,再调用每个属性的set方法将value作为参数传入,来完成对象实例化
* 要点:1、必须有空参构造方法;2、所注入属性必须有对应set方法
* @author Long
* @date 2021/3/10 10:26
* @return void
*/
@Test
public void Stu1Test(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("Spring/StudentBean/Stu1ApplicationContext.xml");
/**
* @description: 根据bean的name在容器中获取对象
*/
Student student = (Student) applicationContext.getBean("student");
System.out.println("属性注入=====" + student);
}
/**
*
* @description: 构造器注入测试
* @remarks: 执行原理:(Stu2ApplicationContext)调用类的有参数构造方法,按index对应参数位置传入value参数创建对象
* 要点:1、类中必须包含每个constructor-arg标签对应的参数的构造方法
* @author Long
* @date 2021/3/10 10:34
* @return void
*/
@Test
public void Stu2Test(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("Spring/StudentBean/Stu2ApplicationContext.xml");
/**
* @description: 根据bean的name在容器中获取对象
*/
Student student = (Student) applicationContext.getBean("student");
System.out.println("构造器注入=====" + student);
}
/**
*
* @description: 注解注入测试
* @remarks: 执行原理:(Stu3ApplicationContext)<context:component-scan>扫描查找标有构造性注解的类,
* 诸如【@Component(组件),@Service(服务),@Controller(控制器),@Repository(数据仓库)】的注解所标注的类,
* 将其注入到容器中。在注解上如果不指定name,那么程序默认将其类名的首字母小写的名称当做name
* 要点:1、需要在xml配置<context:component-scan>来扫描我们使用注解注入的类或其多级父包
* 2、如未在注解上指定name属性,程序自动按照类名的首字母小写名来注入
* @author Long
* @date 2021/3/10 12:46
* @return void
*/
@Test
public void Stu3Test(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("Spring/StudentBean/Stu3ApplicationContext.xml");
/**
* @description: 根据bean的name在容器中获取对象
*/
Student student = (Student) applicationContext.getBean("student");
System.out.println("注解注入=====" + student);
}
- 包目录结构参考