原型模式:Spring 支持将 Bean 对象的作用域设置为 prototype,即每次获取该 Bean 对象时都会创建一个新的实例。
<bean id="myBean" class="com.example.MyBean" scope="prototype" />
在 Spring 中,原型模式主要应用在 Bean 对象的创建过程中。在 Spring 容器中,Bean 的默认作用域是单例(Singleton),即每个 Bean 对象在容器中只有一个实例。但是,有些情况下,我们需要每次获取 Bean 时都创建一个新的实例,此时就需要使用原型模式。Spring 容器中的原型模式是通过 BeanFactory 接口中的 getBean 方法实现的。当 getBean 方法被调用时,Spring 容器会创建一个新的 Bean 实例,并返回给调用方。
下面是一个使用原型模式的示例代码:
@Component
@Scope("prototype")
public class UserService {
private String name;
public void setName(String name) {
this.name = name;
}
public void sayHello() {
System.out.println("Hello, " + name);
}
}
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService1 = context.getBean(UserService.class);
userService1.setName("Alice");
userService1.sayHello();
UserService userService2 = context.getBean(UserService.class);
userService2.setName("Bob");
userService2.sayHello();
}
在上面的代码中,我们使用了 @Scope(“prototype”) 注解来将 UserService Bean 的作用域设置为原型模式。在 main 方法中,我们从容器中获取了两个 UserService Bean,分别设置了不同的 name 属性并调用了 sayHello 方法。由于 UserService Bean 的作用域是原型模式,因此每次获取 Bean 时都会创建一个新的实例,从而实现了每个 Bean 实例之间的隔离。
在 Spring 中,原型模式的实现是通过 ObjectFactory 接口和 ObjectProvider 接口实现的。这两个接口都是提供了获取 Bean 实例的方法,其中 ObjectFactory 接口是基于单个 Bean 定义的,而 ObjectProvider 接口则是基于多个 Bean 定义的。在 Bean 创建时,Spring 容器会为每个原型 Bean 实例都创建一个对应的 ObjectFactory 或 ObjectProvider 实例,用于在运行时动态创建 Bean 实例。
在实现上,Spring 使用了 CGLIB 库来实现原型模式。CGLIB 是一个基于 ASM 库的代码生成库,它可以在运行时动态生成字节码,并创建出新的 Bean 实例。因此,使用原型模式的 Bean 在创建时会比较耗时,特别是在 Bean 中包含大量的属性和依赖时,会导致应用的性能下降。因此,在实际开发中,需要根据具体的业务需求和性能要求来选择使用原型模式还是单例模式。