scope="prototype"和factory结合的案例

问题如下

Ioc03Test.java(要求配置Spring,让测试方法全部测试通过)

package com.yc.test;


import org.junit.Assert;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.yc.test.bank.bean.Account;
/**
 * 配置Spring,让测试方法全部测试通过
 */
public class Ioc03Test {
	ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("IOC02.xml");
	@Test
	public void test1() {
		Account a = cxt.getBean(Account.class);
		Account b = cxt.getBean(Account.class);
		Account c = (Account) cxt.getBean("account");
		Assert.assertEquals(a, b);  // a == b
		Assert.assertEquals(c, b);	// c == b
	}

	@Test
	public void test2() {
		Account a = (Account) cxt.getBean("account1");
		Account b = (Account) cxt.getBean("account1");
		Account c = (Account) cxt.getBean("account1");
		Assert.assertNotEquals(a, b);
		Assert.assertNotEquals(c, b);
		Assert.assertNotEquals(c, a);
	}
	
	@Test
	/**
	 * 工厂方法 (动态 or 静态)
	 */
	public void test3() {
		Account a1 = (Account) cxt.getBean("account2");
		Account a2 = (Account) cxt.getBean("account2");
		Account a3 = (Account) cxt.getBean("account3");
		Account a4 = (Account) cxt.getBean("account3");
		Assert.assertEquals(a1, a2);// a1 == a2
		Assert.assertEquals(a3, a4);// a3 == a4
		
		Assert.assertEquals(a1, a3);
		Assert.assertEquals(a2, a4);
	}
	
	/**
	 * 坑。。。
	 */
	
	@Test
	public void test4() {
		Account a1 = (Account) cxt.getBean("account4");
		Account a2 = (Account) cxt.getBean("account4");
		Account a3 = (Account) cxt.getBean("account4");
		Account a4 = (Account) cxt.getBean("account4");
		Account a5 = (Account) cxt.getBean("account4");
		Account a6 = (Account) cxt.getBean("account4");
		Account a7 = (Account) cxt.getBean("account4");
		
		Assert.assertNotEquals(a1, a2);
		Assert.assertNotEquals(a1, a3);
		Assert.assertNotEquals(a1, a4);
		Assert.assertEquals(a4, a5);
		Assert.assertEquals(a4, a6);
		Assert.assertEquals(a4, a7);
	}
}

Account.java

package com.yc.test.bank.bean;

import org.springframework.stereotype.Component;

/**
 * 银行账户
 * @author Administrator
 *
 */
@Component("account")   // 组件 表示该类是spring管理的   bean   @Bean
public class Account {
	
	private Integer id;		// 主键
	private String name;	// 姓名
	private Double money;	// 余额
	
	public static int i = 0;
	
	
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	} 
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Double getMoney() {
		return money;
	}
	public void setMoney(Double money) {
		this.money = money;
	}
	/**
	 * 这是一个不完整的单例模式,少了私有的构造方法
	 */
	private static Account singleAccount; 
	public static Account getInstance() {
		if(singleAccount == null) {
			singleAccount = new Account();
		}
		return singleAccount;
	}
	@Override
	public String toString() {
		return "Account [id=" + id + ", name=" + name + ", money=" + money + "]";
	}

}

接下来的代码就是要你配置的Spring(也就是答案)

IOC02.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context.xsd">
   
      
     <bean id="account" class="com.yc.test.bank.bean.Account" primary="true"> </bean>
    
     <bean id="account1" class="com.yc.test.bank.bean.Account" scope="prototype" >
     	
     </bean>
     
     <bean id="accfactory" class="com.yc.test.factory.AccountFactory"> </bean>
     
     <!-- 创建一次AccountFactory实例  -->
     <bean id="account2" class="com.yc.test.bank.bean.Account"
      factory-bean="accfactory" factory-method="getAccount" scope="prototype">
     	
     </bean>
     
     <!-- 创建一次AccountFactory实例  -->
     <bean id="account3" class="com.yc.test.bank.bean.Account" 
     factory-bean="accfactory" factory-method="getAccount" scope="prototype">
     		
     </bean>
     
     <!-- 创建一次AccountFactory实例  -->
       <bean id="account4" class="com.yc.test.bank.bean.Account" scope="prototype"
     factory-bean="accfactory" factory-method="getAccount" >
     	
     </bean>
 </beans>

AccountFactory.java

package com.yc.test.factory;

import com.yc.test.bank.bean.Account;

public class AccountFactory {
	
	public Account getAccount(){
		System.out.println("您好,我是实例工厂");
		
		return Account.getInstance();
	}
}

分析

    上面的IOC02.xml是要你写的但是只能成功运行Test1到3。无法运行test4

    在这里我讲解一下test4的解决方案

@Test
	public void test4() {
		Account a1 = (Account) cxt.getBean("account4");
		Account a2 = (Account) cxt.getBean("account4");
		Account a3 = (Account) cxt.getBean("account4");
		Account a4 = (Account) cxt.getBean("account4");
		Account a5 = (Account) cxt.getBean("account4");
		Account a6 = (Account) cxt.getBean("account4");
		Account a7 = (Account) cxt.getBean("account4");
		
		Assert.assertNotEquals(a1, a2);
		Assert.assertNotEquals(a1, a3);
		Assert.assertNotEquals(a1, a4);
		Assert.assertEquals(a4, a5);
		Assert.assertEquals(a4, a6);
		Assert.assertEquals(a4, a7);
	}

根据代码可以看出要想使test4能够执行必须满足  (a1与a2,a3,a4不是一个对象   a4与a5,a6,a7是一个对象)

a1与a2,a3,a4不是一个对象  我们知道可以将scope设置为原型prototype

a4与a5,a6,a7是一个对象   我们知道可以将scope设置为单例singleton 或者用静态工厂或者实例工厂(动态工厂)

但要两者都满足所以只能将scope设置为原型prototype  并且 采用静态工厂或者实例工厂 在这里我用实例工厂

所以IOC02.xml代码为

<bean id="account4" class="com.yc.test.bank.bean.Account" scope="prototype"
     factory-bean="accfactory" factory-method="getAccount" >
     	
     </bean>

但是这样还不行因为单单这样只能保证得到的都是单例对象

 scope="prototype"和factory结合的原理

首先给大家看一个现象

  将Ioc03Test.java的test4改为如下

@Test
	public void test4() {
		Account a1 = (Account) cxt.getBean("account4");
		Account a2 = (Account) cxt.getBean("account4");
		Account a3 = (Account) cxt.getBean("account4");
		Account a4 = (Account) cxt.getBean("account4");
		Account a5 = (Account) cxt.getBean("account4");
		Account a6 = (Account) cxt.getBean("account4");
		Account a7 = (Account) cxt.getBean("account4");
		System.out.println(a1 == a2);
		System.out.println(a1 == a3);
		System.out.println(a1 == a4);
		System.out.println(a4 == a5);
		System.out.println(a4 == a6);
		System.out.println(a4 == a7);
//		Assert.assertNotEquals(a1, a2);
//		Assert.assertNotEquals(a1, a3);
//		Assert.assertNotEquals(a1, a4);
//		Assert.assertEquals(a4, a5);
//		Assert.assertEquals(a4, a6);
//		Assert.assertEquals(a4, a7);
	}

输出结果为

您好,我是实例工厂
您好,我是实例工厂
您好,我是实例工厂
您好,我是实例工厂
您好,我是实例工厂
您好,我是实例工厂
您好,我是实例工厂
true
true
true
true
true
true

通过结果我们可以知道当用scope="prototype"时,每实例话一个对象就会调用一次AccountFactory类的getAccount方法。

根据这个原理我们只要通过实例化的次数来控制是需要产生相同的对象还是不同的对象。

所以最终AccountFactory.java的代码如下

package com.yc.test.factory;

import com.yc.test.bank.bean.Account;

public class AccountFactory {
	public static  int i = 0;//来得到实例化的次数  
	public Account getAccount(){
		i++;
		if(i>=5&&i<=7){
			return new Account();//在产生a1到a3时创建不同对象
		}
		return Account.getInstance();//a4到a7产生相同对象
	}
}

这边i从5开始是由于test3那边我用了scope="prototype"和实例工厂的缘故

要求

执行Ioc03Test时,必须将tset1到test4一起执行。否则无法通过测试

 

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值