Spring教程03-Bean实例化

阅读原文

1、Spring IoC容器和Bean简介

1.1、什么是IOC

IoC又叫依赖注入(DI)。它描述了对象的定义和依赖的一个过程,也就是说,依赖的对象通过构造参数、工厂方法参数或者属性注入,当被依赖的对象实例化后依赖的对象才会被创建, 正常情况下我们因该是先创建一个对象而后去使用它,现在这个过程被反向执行,因此命名为控制反转(IoC)。如下图:
在这里插入图片描述
以上是Spring官方文档给出的关于SpringIoC的解释,下面我简单举个例子来理解一下IoC原理:
场景:公司员工出差
一般情况下,一个员工要出差,首先我们得向人事部门申请出差,然后去找乘车路线,酒店地址,业务对接联系人,出差完了以后,还要整理各种票据来报销出差费用,这样就导致了员工在出差时不但要考虑公司业务洽谈问题,还要考虑各种行程安排以及出差报销,对于员工来说也是很苦恼的,而且更苦恼的是每次出差都要经历这些;
那么我们开始幻想,假如公司有这么一个智能部门,当员工需要出差时,只需要提供自己的诉求清单,比如出差时间、地点、见的人、洽谈的业务等等,员工不参与具体安排事宜,等到出差的那一天,员工只要按照智能部门提供的相关信息去洽谈业务即可,这样一来员工只需要把心思放在洽谈业务本身上,而不需要顾忌其他的事情,岂不是又方便又有效率。
场景映射:IOC
员工:开发人员;出差相关事宜:对象实例,工厂实现,事务控制等等;业务洽谈:核心业务开发;票据报销:数据库连接关闭、对象销毁等等
开发人员要开发核心业务还要把心思花费在业务层对象如何创建、数据库连接如何关闭、事务如何控制、对象如何销毁等等;
智能部门:SpringIOC容器,有了它以后,我们开发人员只需要关注核心业务的实现,其他事情全交由Spring去管理,我们只需要按照Spring提供的配置方式定义自己的诉求,比如:对象之间的关系、那些需要事务控制等等,Spring会帮我们自动完成,这样岂不是很方便。

1.2、基于配置文件创建一个Bean

首先定义一个Java类命名为Student.java

public class Student {
    private String stuNo;
    private String stuName;
    private Integer stuAge;
    public String getStuNo() {
        return stuNo;
    }
    public void setStuNo(String stuNo) {
        this.stuNo = stuNo;
    }
    public String getStuName() {
        return stuName;
    }
    public void setStuName(String stuName) {
        this.stuName = stuName;
    }
    public Integer getStuAge() {
        return stuAge;
    }
    public void setStuAge(Integer stuAge) {
        this.stuAge = stuAge;
}
public void sayHello() {
        System.out.println("****************Spring你好!Spring HelloWord!******************");
    }
}

然后创建一个Spring元数据配置文件命名为application.xml,并把Student.java这个类注入到Spring的IOC容器中, 代码如下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--学生实体-->
    <bean id="student" class="com.java.roads.entity.Student"></bean>
</beans>

配置文件中:每一个bean节点代表Spring所托管的一个Bean对象,其中id为这个bean在Spring容器中的唯一标识;class为类所处的完整类路径(包+类名称)。

1.3、实例化一个Bean容器

Spring通过使用ApplicationContext来实例化一个Bean容器,我们可以使用其提供的构造方加载任何可加载路径的Spring元数据配置文件,本节我们通过加载类路径中的配置文件,完成Spring容器的实例化,同时调用我们Bean中的SayHello方法,代码如下:

public class LoadBean {
    public static Logger logger = LoggerFactory.getLogger(LoadBean.class);
    public static void main(String[] args) {
        //实例化Spring容器
        ApplicationContext  applicationContext = new ClassPathXmlApplicationContext("application.xml");
        //或得Spring实例化好的StudentBean对象
        Student student = applicationContext.getBean(Student.class);
        //调用bean方法
        student.sayHello();
    }
}

运行结果如下:

21:03:37,603 DEBUG main support.ClassPathXmlApplicationContext:590 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@49993335
21:03:38,400 DEBUG main xml.XmlBeanDefinitionReader:395 - Loaded 1 bean definitions from class path resource [application.xml]
21:03:38,468 DEBUG main support.DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'student'
****************Spring你好!Spring HelloWord!******************

通过运行结果可以看到,我们SayHello方法已成功打印了我们想要打印的内容,至此我们已经完成了一个普通的javal类从注入到自动实例再到方法调用的整个过程,下面我们深入了解一下bean。

1.4、Bean概述

1.4.1、Bean的命名

每个bean都有一个或多个标识符。这些标识符在托管bean的容器中必须是唯一的。bean通常只有一个标识符。但是,如果它需要多个,则额外的可以被视为别名。
在基于XML配置的元数据中,我们可以使用id属性,name属性或两者来指定bean标识符。该id属性允许我们自定义一个id。通常,这些名称是字母数字(‘myBean’,'someService’等),但它们也可以包含特殊字符。如果要为bean引入其他别名,还可以在name 属性中指定它们,用逗号(,),分号(;)或空格分隔。
如果我们不想为一个bean提供 name或id,那么容器会自动为该bean生成一个唯一的标识。但是,如果我们需要通过名称引用该bean,或者通过使用ref元素或 Service Locator方式引用Bean,则该Bean必须提供名称。
容器为bean自动命名规则:
通常是在命名bean时使用标准的Java类对象名称约定作为实例字段名称。也就是说,bean名称以小写字母开头,并从那里开始驼峰。比如: student, studentService,studentDao,studentController等等。但需要注意的是,如果我们的需要注入的类名包含多个大写字母开头,则会以原类名称作为bean的唯一标识,例如:TTTStudent、HTSchool等等。

1.4.2、Bean的实例化

1.4.2.1、构造方法实例化

通常,spring容器本身会通过反向调用其构造函数直接创建bean的实例化对象类, 其创建方式类似于我们通过java的new关键字实例化一个对象。

<!—通过构造方法实例化一个bean -->
<bean id="student" class="com.java.roads.entity.Student"></bean>

为了方便期间我们在该类的无参构造方法中打印“确实执行了构造方法”这样一句话,来验证以上观点,代码片段如下:

public class Student {
    private String stuNo;
    private String stuName;
    private Integer stuAge;
    public Student() {
        System.out.println("确实执行了构造方法");
}
}

运行结果如下:

22:06:53,803 DEBUG main support.ClassPathXmlApplicationContext:590 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@49993335
22:06:54,134 DEBUG main xml.XmlBeanDefinitionReader:395 - Loaded 1 bean definitions from class path resource [application.xml]
22:06:54,198 DEBUG main support.DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'student'
确实执行了构造方法
****************Spring你好!Spring HelloWord!******************

我们可以看到确实执行了,该类的无参构造方法;

1.4.2.2、通过静态工厂方法实例化Bean

首先我们定义一个静态工厂,命名为ObjectFactory.java,代码如下:

public class ObjectFactory {
    //手动实例对象
    public static Student student = new Student();
    public ObjectFactory() {
    }
    //静态方法获得Student对象实例
    public static Student createStudentObj() {
        System.out.println("对象实例来自静态工厂...");
        return  student;
    }
}

配置文件如下:

<bean id="student" class="com.java.roads.factory.ObjectFactory" factory-method="createStudentObj">
</bean>

此配置中通过调用工厂方法来创建bean。该定义未指定返回对象的类型,仅仅指定了工厂方法的类。在此示例中,该createStudentObj () 方法必须是静态方法。
运行结果如下:

22:33:25,433 DEBUG main support.ClassPathXmlApplicationContext:590 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@49993335
22:33:25,737 DEBUG main xml.XmlBeanDefinitionReader:395 - Loaded 1 bean definitions from class path resource [application.xml]
22:33:25,814 DEBUG main support.DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'student'
对象实例来自静态工厂...
Disconnected from the target VM, address: '127.0.0.1:52817', transport: 'socket'
****************Spring你好!Spring HelloWord!******************

由运行结果可以看出,对象的实例确实是通过静态工厂的createStudentObj()方法获取的。下面我们来看通过静态工厂获取多个不同的实例该如何配置。

我们再创建两个类,分别为School.java、Class.java代码如下:

public class Class {
    private String claNo;
    private String claName;
    public Class() {
}
//setter、getter略
}
public class School {
    private String schNo;
    private String schName;
    public School() {
        System.out.println("我是学校类...");
}
//setter、getter略
}

然后,我们也通过静态工厂提供的静态方法获取对象实例。
修改静态工厂类代码如下:

public class ObjectFactory {
    //手动实例对象
    public static Student student = new Student();
    public static School school = new School();
    public static Class cla = new Class();
    public ObjectFactory() {
    }
    //获得Student对象实例
    public static Student createStudentObj() {
        System.out.println("Student对象实例来自静态工厂...");
        return  student;
    }
    //获得School对象实例
    public static School createSchoolObj() {
        System.out.println("School对象实例来自静态工厂...");
        return  school;
    }
    //获得Class对象实例
    public static Class createClassObj() {
        System.out.println("Class对象实例来自静态工厂...");
        return  cla;
    }
}

修改spring元数据配置文件如下:

<!--通过静态工厂实例-->
<bean id="student" class="com.java.roads.factory.ObjectFactory" 
factory-method="createStudentObj"></bean>
<bean id="cla" class="com.java.roads.factory.ObjectFactory" 
factory-method="createClassObj"></bean>
<bean id="school" class="com.java.roads.factory.ObjectFactory" 
factory-method="createSchoolObj"></bean>

运行loadBean中的Main方法,结果如下:

Connected to the target VM, address: '127.0.0.1:52998', transport: 'socket'
22:49:40,544 DEBUG main support.ClassPathXmlApplicationContext:590 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@49993335
22:49:40,821 DEBUG main xml.XmlBeanDefinitionReader:395 - Loaded 3 bean definitions from class path resource [application.xml]
22:49:40,893 DEBUG main support.DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'student'
Student对象实例来自静态工厂方法获取...
22:49:40,927 DEBUG main support.DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'cla'
Class对象实例来自静态工厂方法获取...
22:49:40,928 DEBUG main support.DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'school'
School对象实例来自静态工厂方法获取...

由此可见,我们已经通过静态工厂方法成功的创建了多个实例。

1.4.2.3、通过实例化工厂来实例化Bean

修改spring元数据配置如下:

<!--注入工厂-->
<bean id="objectFactory" class="com.java.roads.factory.ObjectFactory"></bean>
<bean id="student"  factory-bean="objectFactory" factory-method="createStudentObj"></bean>
<bean id="cla"  factory-bean="objectFactory" factory-method="createClassObj"></bean>
<bean id="school" factory-bean="objectFactory" factory-method="createSchoolObj"></bean>

其中,factory-bean指的就是我们的工厂类,factory-method指的是我们的工厂方法,此时的工厂方法不是静态的。

修改工厂类代码如下:

public class ObjectFactory {
    //手动实例对象
    public static Student student = new Student();
    public static School school = new School();
    public static Class cla = new Class();
    public ObjectFactory() {
    }
    //获得Student对象实例
    public  Student createStudentObj() {
        System.out.println("Student对象实例来自实例化工厂...");
        return  student;
    }
    //获得School对象实例
    public  School createSchoolObj() {
        System.out.println("School对象实例来自实例化工厂...");
        return  school;
    }
    //获得Class对象实例
    public  Class createClassObj() {
        System.out.println("Class对象实例来自实例化工厂...");
        return  cla;
    }
}

运行loadBean中的Main方法,结果如下:

23:50:15,234 DEBUG main support.ClassPathXmlApplicationContext:590 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@49993335
23:50:15,579 DEBUG main xml.XmlBeanDefinitionReader:395 - Loaded 4 bean definitions from class path resource [application.xml]
23:50:15,663 DEBUG main support.DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'objectFactory'
23:50:15,690 DEBUG main support.DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'student'
Student对象实例来自实例化工厂...
23:50:15,694 DEBUG main support.DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'cla'
Class对象实例来自实例化工厂...
23:50:15,695 DEBUG main support.DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'school'
School对象实例来实例化工厂...

由此看见,我们已经成功的通过实例化工厂获取了bean的实例,这种方法也表明可以通过依赖注入(DI)的方式来管理和配置我们自定义的工厂bean本身。

更多最新技术文章,请关注“冰点IT”公众号

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值