Spring、Spring依赖注入与编码剖析Spring依赖注入的原理
Spring依赖注入
新建PersonIDao 和PersonDao底实现Save方法:
public interface PersonIDao {
public void save();
}
public class PersonDaoImpl implements PersonIDao{
@Override
public void save() {
System.out.println("我是dao的Save方法");
}
}
在Bean.xml中注入PersonIDao,并将PersonIDao注入到PersonService中:
<bean id="personIDao" class="cn.dao.impl.PersonDaoImpl" />
<bean id="personIService" class="cn.server.impl.PersonServiceImpl">
<property name="personIDao" ref="personIDao" />
</bean>
在PersonService中添加PersonIDao类型属性并实现属性的set方法,然后调用PersonIDao的save方法
public class PersonServiceImpl implements PersonIService {
private PersonIDao personIDao; public PersonIDao getPersonIDao() {
return personIDao;
}
public void setPersonIDao(PersonIDao personIDao) {
this.personIDao = personIDao;
}
@Override
public void save() {
personIDao.save();
}
}
然后测试:
@Test
public void testSave() {
AbstractApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
PersonIService personIService=(PersonIService)ac.getBean("personIService");
personIService.save();
}
编码剖析Spring依赖注入的原理
通过编码的方法式来剖析Spring 依赖注入的原理方法,新建PropertyDefinition类用来承载Bean中注入的property的属性:
public class PropertyDefinition {
private String name;
private String ref;
public PropertyDefinition(){}
public PropertyDefinition(String name, String ref) {
super();
this.name = name;
this.ref = ref;
} public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
}
新建BeanDefinition用来承载解析到的Bean属性
public class BeanDefinition {
private String id;
private String className;
private List<PropertyDefinition> properties=new ArrayList<PropertyDefinition>();
public BeanDefinition(){}
public BeanDefinition(String id, String className) {
this.id = id;
this.className = className;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public List<PropertyDefinition> getProperties() {
return properties;
}
public void setProperties(List<PropertyDefinition> properties) {
this.properties = properties;
}
}
新建OtherClassPathXMLApplicationContext 用来解析bean.xml
public class OtherClassPathXMLApplicationContext {
private List<BeanDefinition> list=new ArrayList<BeanDefinition>();
private Map<String,Object> beans=new HashMap<String, Object>(); public OtherClassPathXMLApplicationContext(String fileName){
this.readXML(fileName);
this.instanceBeans();
this.instanceProperties();
}
private void instanceBeans(){
for(BeanDefinition bean : list){
try {
// 创建Bean实例,并放到Map中
if(bean.getClassName()!=null && !bean.getClassName().trim().equals("")){
beans.put(bean.getId(), Class.forName(bean.getClassName()).newInstance());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void instanceProperties(){
for(BeanDefinition beanDefinition : list){
Object bean=beans.get(beanDefinition.getId());
if(bean!=null){
try {
// 获取bean下所有的属性定义描述
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for(PropertyDefinition propertyDefinition : beanDefinition.getProperties()){
for(PropertyDescriptor propertyDescriptor : ps){
// 如果bean下的属性名字与当前的BeanDefinition下的属性名称一样的话,则将引用对象注入到属性
if(propertyDefinition.getName().equals(propertyDescriptor.getName())){
Method setter=propertyDescriptor.getWriteMethod(); // 获取Bean的所有写入的方法 即 setter方法
setter.setAccessible(true); // true: 直接访问私有属性,将例子中的私有属性改值。
Object value=beans.get(propertyDefinition.getRef());
setter.invoke(bean, value); // 把引用对象注入属性
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private void readXML(String fileName){
SAXReader saxReader = new SAXReader();
Document doc=null;
try{
// JAVA里面对于类进行调用配置资源的文件数据,以this.getClass().getResourceAsStream()来读取比较合适。
// 路径采用相对路径直接可以从工程的path路径去找。
URL xmlpath=this.getClass().getClassLoader().getResource(fileName);
doc=saxReader.read(xmlpath);
Map<String,String> nsMap=new HashMap<String,String>();
nsMap.put("ns", "http://www.springframework.org/schema/beans"); // 加入命名空间
XPath xsub=doc.createXPath("//ns:beans/ns:bean"); // 创建 beans/bean的查询路径
xsub.setNamespaceURIs(nsMap); // 设置命名空间
List beans=xsub.selectNodes(doc); // 获取文档下的所有bean节点
for(Object node : beans){
Element element=(Element)node;
String id=element.attributeValue("id");
String className=element.attributeValue("class");
BeanDefinition bean=new BeanDefinition(id,className); // 编码剖析Spring依赖注入的原理
// 加载bean下的Property
XPath xproperty=element.createXPath("ns:property"); // 为xproperty 添加查询路径
xproperty.setNamespaceURIs(nsMap);
List properties=xproperty.selectNodes(element); // 查询出bean下的所有property
for(Object propertyNode : properties){
Element propertyElement=(Element)propertyNode;
String name=propertyElement.attributeValue("name");
String ref=propertyElement.attributeValue("ref");
bean.getProperties().add(new PropertyDefinition(name, ref));
}
list.add(bean);
} }catch(Exception e){
e.printStackTrace();
}
}
// 通过Id名称,获取Bean
public Object getBean(String name){
return beans.get(name);
}
}
测试代码:
@Test
public void testSave2() {
OtherClassPathXMLApplicationContext ac = new OtherClassPathXMLApplicationContext("beans.xml");
PersonIService personIService=(PersonIService)ac.getBean("personIService");
personIService.save();
}
Spring、Spring依赖注入与编码剖析Spring依赖注入的原理的更多相关文章
- (转)编码剖析Spring依赖注入的原理
http://blog.csdn.net/yerenyuan_pku/article/details/52834561 Spring的依赖注入 前面我们就已经讲过所谓依赖注入就是指:在运行期,由外部容 ...
- (转)编码剖析Spring装配基本属性的原理
http://blog.csdn.net/yerenyuan_pku/article/details/52856465 上回我们已经讲到了Spring依赖注入的第一种方式,现在我们来详解第二种方式,须 ...
- (转)编码剖析Spring管理Bean的原理
http://blog.csdn.net/yerenyuan_pku/article/details/52832434 在Spring的第一个案例中,我们已经知道了怎么将bean交给Spring容器进 ...
- (转)编码剖析@Resource注解的实现原理
http://blog.csdn.net/yerenyuan_pku/article/details/52860046 上文我们已经学会使用@Resource注解注入属性.学是学会了,但也仅限于会使用 ...
- Spring、编码剖析Spring管理Bean的原理
引入dom4j jar包 1.新建Person接口和PersonBean public interface PersonIService { public void helloSpring(); } ...
- Spring(八)编码剖析@Resource注解的实现原理
配置文件beans2.xml <?xml version="1.0" encoding="UTF-8"? > <beans xmlns=&qu ...
- Spring第三弹—–编码剖析Spring管理Bean的原理
先附一下编写的Spring容器的执行结果: 代码如下: 模拟的Spring容器类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ...
- 编码剖析Spring管理bean的原理
project目录 MyClassPathXMLApplicationContext读取xml,以及实例化bean. 因为是一开始实例化配置文件所有bean,所以需要构造器完成这些工作. packag ...
- Spring2.5学习3.2_编码剖析@Resource注解的实现原理
首先看一下J2EE提供的@Resource注解:该注解默认安照名称进行装配,名称能够通过name属性进行指定, 假设没有指定name属性,当注解写在字段上时,默认取字段名进行依照名称查找,假设注解写在 ...
随机推荐
- 学习linux之用户-文件-权限操作
添加用户组 添加 gropuadd 用户组名 修改 groupmod 用户组名 删除 groupdel 用户组名 添加用户 添加 useradd 用户名 设密码 passwd 密码 删除 userde ...
- 蜂鸟A20开发板刷 cubietruck 的 SD 卡固件
美睿视讯 为蜂鸟A20准备的 MerriiLinux 功能非常简陋.所以能用上主流的 debian 或者 LUbuntu 就可以说是非常迫切的需求了.蜂鸟A20(Merrii Hummingbird ...
- Winform 窗体设计器 无法识别重复成员变量声明的问题
打开窗体设计视图出现如下错误: 查看后台代码: ColumnHeader colHead; colHead = new ColumnHeader(); colHead.Text = "Ch& ...
- 使用Flask 生成中文图片验证码
因最近要用到验证码,上网搜了下,发现什么验证码感觉都能被攻破,连最近疯传的变态的12306的验证码居然有人一天就攻破了,所以,综合考虑,还是使用汉字: web框架是Flask,然后使用python的I ...
- Red5 1.0 RC1 与tomcat 6 整合
1.0以上版本没整合成功过,如有人整合成功过,也分享下,在此先谢谢 一.下载red5-1.0.0-RC1.zip 下载地址:http://code.google.com/p/red5/ 和http:/ ...
- jsp验证码页面笔记
首先在网上搜了下jsp生成验证码的代码,如下: package com.servlet; import java.awt.Color; import java.awt.Font; import jav ...
- C#基础:事件(二) 【转】
上篇文章介绍了C#中事件的基本实现方式,在本文中,将对最常见的事件委托EventHandler和EventHandler<T>做介绍. 事实上,在前面文章的介绍中,已经涉及到了EventH ...
- 命令行运行命令时报错You don't have write permissions for the /Library/***
这是由于要运行这些操作时必须有管理员的权限(比方更新软件),比方更新cocoapods时报错 soindy:SmartThermo soindy$ gem install cocoapods Fetc ...
- Apple Mach-O Linker Warning 警告解决的方法
此警告解决的方法: 项目名字 -> targets -> Build Settings -> search path 把里面无用的东西 点 减号 删掉 即可了. $(function ...
- Linux学习3——磁盘文件管理系统与压缩和打包操作
一.写在前面 本节将对Linux的磁盘文件系统.文件的压缩打包等操作进行简要介绍. 二.完成目标 1.了解磁盘文件系统的接本知识 2.操作文件和目录的相关命令 3.文件系统的简单操作命令 4.Lin ...