beanfactory IOC

day28_4

package cn.itcast.beanfactory;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;

import cn.itcast.beanfactory.cfg.BeanConfig;
import cn.itcast.beanfactory.cfg.PropertyConfig;
import cn.itcast.beanfactory.factorybean.FactoryBean;
import cn.itcast.beanfactory.utils.BeanFactoryUtils;

public class BeanFactory {
	// 配置文件的对应体
	private Map<String, BeanConfig> bcs = new HashMap<String, BeanConfig>();
	// Bean缓存,id是键, Bean是值
	private Map<String, Object> beanCache = new HashMap<String, Object>();
	
	public BeanFactory(String xmlName) {
		BeanFactoryUtils.load(this, xmlName);
	}
	
	// 如果缓存中存在,直接返回
	// 如果不存在,创建Bean,放入缓存中,再返回
	public Object getBean(String id) {
		BeanConfig bc = bcs.get(id);
		if(bc == null) {
			throw new RuntimeException(id + "不存在!");
		}
		if(bc.getScope() == null || bc.getScope().equals("singleton")) {
			// 如果是单例bean,查看缓存中是否存在,如果存在直接返回
			if(beanCache.containsKey(id)) {
				return beanCache.get(id);
			}
			// 如果缓存中不存在,那么创建之,然后放入缓存中,再返回
			Object bean = createBean(id);
			beanCache.put(id, bean);
			return bean;
		} else if(bc.getScope().equals("prototype")) {
			// 如果是原型bean,那么直接创建,然后返回,不用向入缓存
			Object bean = createBean(id);
			return bean;	
		}
		throw new RuntimeException("scope只能是singleton或prototype");
	}
	
	
	private Object createBean(String id) {
		try {
			BeanConfig bc = bcs.get(id);//获取Bean配置对象
			Class c = Class.forName(bc.getClassName());
			Object bean = c.newInstance();
			Map<String, PropertyConfig> pcs = bc.getPropertyConfigMap();
			// 遍历所有的PropertyConfig
			for(String propName : pcs.keySet()) {
				PropertyConfig pc = pcs.get(propName);
				if(pc.getRef() != null) {
					String ref = pc.getRef();//是不是另一个bean的id
					Object refBean = getBean(ref);
					BeanUtils.setProperty(bean, pc.getName(), refBean);
				} else {
					BeanUtils.setProperty(bean, pc.getName(), pc.getValue());
				}
			}
			if(bean instanceof FactoryBean) {
				FactoryBean factoryBean = (FactoryBean) bean;
				return factoryBean.getObject(); 
			}
			return bean;
		} catch(Exception e) {
			throw new RuntimeException(e);
		}
	}

	public void addBeanConfig(BeanConfig bc) {
		bcs.put(bc.getId(), bc);
	}
	
	public BeanConfig getBeanConfig(String id) {
		return bcs.get(id);
	}

	public Map<String, BeanConfig> getBcs() {
		return bcs;
	}

	public void setBcs(Map<String, BeanConfig> bcs) {
		this.bcs = bcs;
	}
	
	
}
@Test
	public void fun1() {
		/*
		 * 1. 创建Bean工厂,创建时需要给工厂指定配置文件
		 * 2. 从工厂中获取bean对象
		 */
		BeanFactory bf = new BeanFactory("beans.xml");
		Student s1 = (Student)bf.getBean("stu1");//stu1 是bean.xml 当中的id
		Student s2 = (Student)bf.getBean("stu1");
		System.out.println(s1);
		System.out.println(s1 == s2);//验证每一次创建的对象是否是一个
	}

证明是单例模式,但是也是可以配置多例模式

但是以后在配置的过程中一般都是dao service的类才会配置

虽然stu1和stu2 都是引用的t1 老师,但是老师 是同一个

<bean id="stuDao" className="cn.itcast.dao.impl.StudentImpl">
	</bean>

面向接口编程是由spring实现的,最大限度的解耦,如果想更改实现类只需要在spring中配置就可以了,spring 提供了beanfactory(ioc)

例如

只需要更改spring 的配置文件中的实现配置就可以了

struts 和spring mybatis 结合的目的是struts 可以通过spring 把Action 可以在spring 中通过beanfactory进行实例,mybatis 也可以通过spring beanfactory 进行实例化。

猜你喜欢

转载自blog.csdn.net/qq_20610631/article/details/81158680