Sping的三种注入原理浅析

Spring的三种基本注入方式

同篇发布:Spring是如何注入的?

前言:Spring是什么?

用几句白话聊聊Spring两大特性

IOC(控制反转):

  1. 控制反转:将你所控制的对象交给“程序”托管。
  2. 作用:减少你你创建对象时手动书写new的过程。
  3. 原理:它将你所托管的类实例化到一个“大缸”里,在你使用时直接“取出”即可。
  4. 简而言之:如果你要使用某个类:开箱即用。

AOP(切面):

  1. 切面:形如“小三”,半路插上一脚,整个过程相当于第三方“介入”到原有的程序中。
  2. 作用:以“第三人称”的方式遍布全局作为事务/日志/监控等“介入”程序来达到事务控制/日志记录/安全监控等操作,同时又不会影响到程序本身。
  3. 原理:在您正确“告知”(配置)程序哪些地方(代码点)需要“介入”(切入)后,程序运行到这些地方,就会在不影响主程序的情况下同时执行第三方“介入”后的操作。
  4. 抽象白话:假如你上报交通局某个十字路口需要安装红绿灯,当红绿灯安装完成后,就能够正常作为该路段的指示灯来引导交通。
  • 本文代码请在您本机可以正常使用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);
    }
  • 包目录结构参考

在这里插入图片描述

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值