面向接口编程(面向抽象编程)
场景:用户添加
好处:灵活
所以模拟的时候 也是面像接口
首先
public interface BeanFactory {
public Object getBean(String id);
}
然后
public class ClassPathXmlApplicationContext implements BeanFactory{...}
Spring的一个重要功能:动态装配
读配置文件 beans.xml
<beans>
<bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl" />
<bean id="userService" class="com.bjsxt.service.UserService" >
<property name="userDAO" bean="u"/>
</bean>
</beans>
在userService里面有一个属性叫userDao ,更精确的说 应该是userService里面有个方法叫 setUserDao,有了Spring的这个功能 ,它可以帮你把userDao这个属性注入进来,(注入到哪里要看配置文件怎么写,比如这里就把userDao注入到id=“u”的bean里面了)就是说在一个类里面,它的一个重要属性可以在配置文件里面直接指定 , 这个类在生成的时候就指定好了
实现注入
不再这么写死
而是:
//IOC, Inverse of Control ;DI ,Dependency Injection 依赖注入
public ClassPathXmlApplicationContext() throws Exception {
SAXBuilder sb=new SAXBuilder();
Document doc=sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml")); //构造文档对象
Element root=doc.getRootElement(); //获取根元素HD
List list=root.getChildren("bean");//取名字为disk的所有元素
for(int i=0;i<list.size();i++){
Element element=(Element)list.get(i);
String id=element.getAttributeValue("id");
String clazz=element.getAttributeValue("class");
Object o = Class.forName(clazz).newInstance();
System.out.println(id);
System.out.println(clazz);
beans.put(id, o);
for(Element propertyElement : (List<Element>)element.getChildren("property")) {
String name = propertyElement.getAttributeValue("name"); //拿到userDAO属性
String bean = propertyElement.getAttributeValue("bean"); //拿到u 这个bean
Object beanObject = beans.get(bean); //就是当前这个bean的class, UserDAOImpl instance
//拼出setUserDao
String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
System.out.println("method name = " + methodName);
//拼出setUserDao(UserDao.class)
Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
m.invoke(o, beanObject);
}
}
}
IOC【控制反转:原来userDao是由我自己控制,当前类去控制,现在由容器帮我控制】/(DI【依赖注入(userDao是依赖容器,也就是Spring来帮我们注入进来的,而不是自己写死了的】),两者其实是一个意思
1. 把自己new的东西改为由容器提供
a) 初始化具体值
b) 装配
2. 好处:灵活装配