bean配置
bean基础配置
类别 | 描述 |
名称 | bean |
类型 | 标签 |
所属 | beans标签 |
功能 | 定义Spring核心容器管理对象 |
格式 | <beans> <bean/> </beans> |
属性列表 | id:bean的id,使用容器可以通过id值获取对应的bean,在一个容器中id值唯一 class:bean的类型,即配置的bean的全路径类名 |
范例 | <bean id="bookMapper" class="com.xsl.mapper.impl.BookMapperImpl"></bean> |
bean别名配置
类别 | 描述 |
名称 | name |
类型 | 属性 |
所属 | bean标签 |
功能 | 定义bean的别名,可以定义多个,使用逗号(,)分号(;)空格( )分隔 |
范例 | <bean id="bookService" name="service bookService2" class="com.xsl.service.impl.BookServiceImpl"/> |
bean作用范围配置
bean实例化
构造器实例化
构造方法的作用——对对象进行初始化
bean本质上就是对象,构造器实例化是指Spring容器通过bean对应类中默认的无参构造方法来实例化bean。
构造方法
【示例】
重点理解!!!
我们人出生的时候,有些人一出生之后再起名字的,但是有些人一旦出生就已经起好名字了。在这里,创建对象可以理解成“人出生”,而无参构造方法对应“人一出生之后起名字”,全参构造方法参数的传递对应“有些人一旦出生就已经起好名字了”。
在src目录下,创建com.xushilin.pojo包,并创建Baby类:
public class Baby {
public int age; //年龄
public String name; //姓名
//全参构造函数
public Baby(int age, String name) {
this.age = age; //给对象赋予age值
this.name = name; //给对象赋予name值
}
//无参构造函数
public Baby() {
}
//我们人出生的时候,有些人一出生之后再起名字的,但是有些人一旦出生就已经起好名字了。
public static void main(String[] args) {
/*—————————————————Test无参构造方法—————————————————*/
System.out.println("---baby1---");
Baby baby1 = new Baby();
System.out.println("年龄:" + baby1.age + " " + "姓名:" + baby1.name);
/*—————————————————Test全参构造方法—————————————————*/
System.out.println("---baby2---");
Baby baby2 = new Baby(20, "xushilin"); //这个对象创建出来的时候已经有了自己的名字和年龄
/*
* 根据创建对象的实参个数,jvm会去寻找合适的构造方法
* 这里传递了2个两个参数,所以会调用2个参数的构造方法——Baby(int age, String name)
* */
System.out.println("年龄:" + baby2.age + " " + "姓名:" + baby2.name);
}
}
【运行结果】
构造函数也是类里的一个函数,跟普通函数不同,两者区别:
- 普通函数是用于定义对象应该具备的功能。而构造函数定义的是对象在调用它所具备的功能(由一般普通函数定义)前,在建立时应该具备的一些内容,就是对象初始化的内容。
- 构造函数是对象建立时由JVM调用,将对象初始化。普通函数是对象建立以后,当对象调用该功能时才会执行。
- 普通函数可以使用对象多次调用,构造函数就在创建对象时调用。
- 构造函数的函数名要与类名一样,而普通函数只要符合标识符的命名规则即可。
- 构造函数可以用任何访问修饰符(public、protected和private)修饰,不能用static、final、abstract和synchronized等关键字修饰不能用void修饰,构造函数没有返回值类型。
构造函数注意细节
- 当类中没有定义构造函数时,系统会指定给该类加上一个无参构造方法。这个是类中默认的构造函数。如果当类中自定义了构造函数,这时默认的构造函数就没有了。
- 在一个类中可以定义多个构造函数以进行不同的初始化。多个构造函数存在于类中,是以重载的形式体现的——构造函数的名称都相同。
我们要求每个小孩出生都会哭,这份代码有两个构造函数,如果需要每个小孩出生都要哭的话,那么就需要在不同的构造函数中调用cry()函数。
但是,这样子的话造成了代码重复的问题。那么怎么解决这个问题呢?
构造代码块
【运行结果】
构造代码块作用:
给所有对象进行统一的初始化,对象一建立就运行并且优于构造函数。
与构造函数区别:
构造函数是给对应的对象进行初始化,构造代码块是将构造方法中的公共信息提取,给所有对象进行统一初始化。
静态工厂实例化
使用静态工厂是实例化Bean的另一种方式。
该方式要求开发者创建一个静态工厂的方法来创建bean的实例,其bean配置中的class属性所指定的不再是Bean实例的实现类,而是静态工厂类,同时还需要使用factory-method属性来指定所创建的静态工厂方法。
下面通过一个案例来演示如何使用静态工厂方式实例化Bean。
在src目录下,创建com.xushilin.mapper包,并创建BeanMapper接口。
package com.xushilin.mapper;
public interface BookMapper {
public void save();
}
在src目录下,创建com.xushilin.mapper.impl包,并创建BeanMapper接口的实现类BeanMapperImpl。
package com.xushilin.mapper.impl;
import com.xushilin.mapper.BeanMapper;
public class BeanMapperImpl implements BeanMapper {
@Override
public void save() {
System.out.println("bean mapper save...");
}
}
接下来,我们在src目录下,创建com.xushilin.factory包,在这个包内创建一个工厂BeanMapperFactory类,里边有一个静态(static)的方法getBeanMapper,使用它就可以创建对象。
package com.xushilin.factory;
import com.xushilin.mapper.BeanMapper;
import com.xushilin.mapper.impl.BeanMapperImpl;
public class BeanMapperFactory {
public static BeanMapper getBeanMapper(){
return new BeanMapperImpl();
}
}
在com.xushilin包中创建测试类Teat,测试通过静态工厂创建对象:
package com.xushilin;
import com.xushilin.factory.BeanMapperFactory;
import com.xushilin.mapper.BeanMapper;
//以前使用的测试类
public class Test {
public static void main(String[] args) {
//通过静态工厂创建对象
BeanMapper beanMapper = BeanMapperFactory.getBeanMapper();
beanMapper.save();
}
}
以上是常规的使用静态工厂实例化对象。
在Spring中,其bean配置中的class属性所指定的不再是Bean实例的实现类,而是静态工厂类,同时还需要使用factory-method属性来指定所创建的静态工厂方法。
<!--配置:使用静态工厂示例bean-->
<!--factory-method属性告诉Spring容器使用工厂方法getBeanMapper来实例化beanMapper-->
<bean id="beanMapper" class="com.xushilin.factory.BeanMapperFactory" factory-method="getBeanMapper"></bean>
这里首先通过元素的id属性定义了一个名称为beanMapper的Bean,然后由于使用的是静态工厂方法,所以需要通过class 属性指定其对应的工厂实现类为BeanMapperFactory。由于这种方式配置Bean后,Spring 容器不知道哪个是所需要的工厂方法,所以增加了factory- -methand属性来告诉Spring容器,其方法名称为getBeanMapper。
接下来,我们测试一下:
package com.xushilin;
import com.xushilin.mapper.BeanMapper;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
//获取IoC容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取对象
BeanMapper beanMapper = (BeanMapper) ctx.getBean("beanMapper");
beanMapper.save();
}
}
【运行结果】
成功使用静态工厂实例化了BeanMapper对象!
实例工厂实例化
这种方式的工厂类中,不再使用静态方法创建Bean实例,而是采用直接创建Bean实例的方式。同时,在配置文件中,需要实例化的Bean也不是通过class属性直接指向的实例化类,而是通过factory- bean属性指向配置的实例工厂,然后使用factory-method属性确定使用工厂中的哪个方法。下面通过一一个案例来演示实例工厂方式的使用。
首先创建BeanMapper接口以及BeanMapper接口的实现类BeanMapperImpl,具体内容参照上面,在此不做赘述。
接下来,我们在com.xushilin.factory包内创建一个工厂BeanMapperFactory类,里边有一个方法getBeanMapper,使用它就可以创建对象。
//实例工厂实例化
public BeanMapper getBeanMapper(){
return new BeanMapperImpl();
}
然后我们去Spring的配置文件中配置工厂bean
<!--
解读:
其中先配置工厂bean,然后配置需要实例化的bean,
通过factory-bean属性指向工厂bean,
通过factory-method属性告诉Spring容器使用工厂方法getBeanMapper()来实例化beanMapper,
实例化的Bean的id为beanMapper
-->
<!--配置工厂-->
<bean id="beanMapperFactory" class="com.xushilin.factory.BeanMapperFactory"></bean>
<!--使用使用factory-bean属性指向配置的实例工厂,使用factory-method属性确定使用工厂中的哪个方法-->
<bean id="beanMapper" factory-method="getBeanMapper" factory-bean="beanMapperFactory"></bean>
接下来,我们测试一下:
public class Test {
public static void main(String[] args) {
//创建实例工厂对象
BeanMapperFactory beanMapperFactory = new BeanMapperFactory();
BeanMapper beanMapper = beanMapperFactory.getBeanMapper();
beanMapper.save();
// //获取IoC容器
// ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// BeanMapper beanMapper = (BeanMapper) ctx.getBean("beanMapper");
// beanMapper.save();
}
}
解读
其中先配置工厂bean,然后配置需要实例化的bean,通过factory-bean属性指向工厂bean,通过factory-method属性告诉Spring容器使用工厂方法getBeanMapper()来实例化beanMapper,实例化的Bean的id为beanMapper。
静态工厂实例化与实例工厂实例化对比:
不足:
综上三种实例化的方式,可以看出实例化方式的不同主要集中于配置文件beans上,不同的实例化方式所要求的东西,或许有所不同。但是归根结底还是IoC容器的实例化bean的方式。这也是Spring中的核心概念之一。