Spring 对 Bean 的管理
主要对 spring bean的管理细节进行参数,使用的案例是之前的保存账户的例子(为方便阐述,会对之前的代码进行一些调整),文末会有全部的源码。
为了方便阐述,在这里先贴一下相关文件内容:
- wiki.laona.service.impl.AccountServiceImpl 类代码
package wiki.laona.service.impl;
import wiki.laona.service.IAccountService;
public class AccountServiceImpl implements IAccountService {
@Override
public void saveAccount() {
System.out.println("Service 中的 saveAccount 执行了~!");
}
}
- wiki.laona.service.IAccountService 类代码
package wiki.laona.service;
/**
* @description: 账户业务层接口
**/
public interface IAccountService {
// 模拟保存
void saveAccount();
}
- wiki.laona.ui.AccountDemo 类代码:
package wiki.laona.ui;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import wiki.laona.service.IAccountService;
/**
* @description: 模拟表现层,用于调用业务层
**/
public class AccountDemo {
public static void main(String[] args) {
// 获取核心容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
// 根据 id 获取 bean 对象
IAccountService as = (IAccountService) applicationContext.getBean("accountService");
as.saveAccount();
}
}
- resources.bean.xml 代码:
<?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-3.0.xsd">
<!-- 把对象的创建交给 spring 来管理-->
<!-- 在此添加相应的配置信息 -->
</beans>
- pom.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<groupId>org.example</groupId>
<artifactId>SpringIOCTest</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
</dependencies>
</project>
1 创建 bean 的三种方式
1.1 使用默认构造函数创建
在 spring 的配置文件中,使用 bean 标签,配以 id 和 class 属性之后,且没有其他属性和标签时。采用的就是默认构造函数创建 bean 对象,此时如果勒种没有默认构造函数,则对象无法创建
- res 下的 bean.xml 文件内容
<!-- 获取 bean 对象 -->
<bean id="accountService" class="wiki.laona.service.impl.AccountServiceImpl"/>
运行 AccountDemo 的 main 方法,打印结果为:
service 中的 saveAccount 执行了~!
这是因为在获取的 AccountServiceImpl 类中,没有重写任何构造方法,故默认调用无参构造方法,如果在 AccountServiceImpl 中添加一个有参构造函数
public AccountServiceImpl(String name){}
那么运行结果会是这样:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [wiki.laona.service.impl.AccountServiceImpl]
重写了有参构造函数,系统将不会提供无参构造函数。故初始化错误。
在实际开发中,我们有可能会使用别人写好的 jar 包进行开发,jar 包中的类是以字节码的方式存在,我们无法修改,这这种情况下我们怎么使用呢?
下面我们就来模拟下这种情况,我们这里使用 InstanceFactory 类来模拟。
- 创建 factory.InstanceFactory 类,如下:
package wiki.laona.factory;
import wiki.laona.service.IAccountService;
import wiki.laona.service.impl.AccountServiceImpl;
/**
* @program: SpringIOCTest
* @description: 模拟一个工厂类(该类可能是存在于 jar 包中 , 无法通过修改源码的方式来提供默认构造函数)
* @author: laona
* @create: 2020-03-26 15:42
**/
public class InstanceFactory {
public IAccountService getAccountService() {
return new AccountServiceImpl();
}
}
那个这种方式的对象如何创建呢,第二种方式就来了。
1.2 工厂模式创建对象
使用普通工厂中的方法创建对象(使用某个类方法创建对象,并存入 spring 容器中)
我们的目标是得到 AccountServiceImpl ,所以我们需要通过 IAccountService 对象的 getAccountService() 方法获取。
- 配置 bean.xml 文件
<!--获取 instanceService 对象-->
<bean id="instanceService" class="wiki.laona.factory.InstanceFactory"></bean>
<!-- 通过instanceService 对象拿到 getAccountService 方法 -->
<bean id="accountService" factory-bean="instanceService" factory-method="getAccountService"></bean>
其中,factory-bean 是获取工厂对象的实例,factory-method 是获取对象方法。
以上便是通过工厂模式创建对象,也是莫得问题的。
那么说,我们在类中有普通方法也有静态方法。静态方法如何获取 bean 对象的呢?
1.3 静态方法创建对象
使用工厂模式中的方法创建对象(使用某个类中的静态方法创建对象),并存入 spring 中
- 新建 factory.StaticFactory 类:
package wiki.laona.factory;
import wiki.laona.service.IAccountService;
import wiki.laona.service.impl.AccountServiceImpl;
public class StaticFactory {
public static IAccountService getAccountService() {
return new AccountServiceImpl();
}
}
- 获取到 StaticFactory 对象
<bean id="accountService" class="wiki.laona.factory.StaticFactory">
好了,到这里我们思考一个问题,通过上面的配置文件,我们获取到的对象是 StaticFactory ,但是我们想要拿到的 bean 却是 accountService 的对象实例。同时因为是静态方法,所以我们通过 factory-method 属性就能拿到 accountService 的对象。
- 获取 accountService 对象
<bean id="accountService" class="wiki.laona.factory.StaticFactory" factory-method="getAccountService"></bean>
这样就拿到 accountService 了。
以上便是创建 bean 的三种方式。