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 进行实例化。