首先看一下J2EE提供的@Resource注解:该注解默认安照名称进行装配,名称能够通过name属性进行指定, 假设没有指定name属性,当注解写在字段上时,默认取字段名进行依照名称查找,假设注解写在setter方法上默认取属性名进行装配。

当找不到与名称匹配的bean时才依照类型进行装配。可是须要注意的是,假设name属性一旦指定。就仅仅会依照名称进行装配。

这里我们模拟@Resource注解,便于理解注解的实现原理:

1.首先在前面模拟的容器中加入注入的方法annotationInject();

XjjClassPathXMLApplicationContext.java

package junit.test;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.apache.commons.beanutils.ConvertUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader; /**
* Xjj版容器
*
*/
public class XjjClassPathXMLApplicationContext {
private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
private Map<String, Object> sigletons = new HashMap<String, Object>(); public XjjClassPathXMLApplicationContext(String filename){
this.readXML(filename);
this.instanceBeans();
this.annotationInject();
this.injectObject();
}
/**
* 通过注解实现注入依赖对象
*/
private void annotationInject() {
for(String beanName : sigletons.keySet()){
Object bean = sigletons.get(beanName);
if(bean!=null){
try {
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for(PropertyDescriptor properdesc : ps){
Method setter = properdesc.getWriteMethod();//获取属性的setter方法
if(setter!=null && setter.isAnnotationPresent(XjjResource.class)){
XjjResource resource = setter.getAnnotation(XjjResource.class);
Object value = null;
if(resource.name()!=null && !"".equals(resource.name())){
value = sigletons.get(resource.name());
}else{
value = sigletons.get(properdesc.getName());
if(value==null){
for(String key : sigletons.keySet()){
if(properdesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())){
value = sigletons.get(key);
break;
}
}
}
}
setter.setAccessible(true);
setter.invoke(bean, value);//把引用对象注入到属性
}
}
Field[] fields = bean.getClass().getDeclaredFields();
for(Field field : fields){
if(field.isAnnotationPresent(XjjResource.class)){
XjjResource resource = field.getAnnotation(XjjResource.class);
Object value = null;
if(resource.name()!=null && !"".equals(resource.name())){
value = sigletons.get(resource.name());
}else{
value = sigletons.get(field.getName());
if(value==null){
for(String key : sigletons.keySet()){
if(field.getType().isAssignableFrom(sigletons.get(key).getClass())){
value = sigletons.get(key);
break;
}
}
}
}
field.setAccessible(true);//同意訪问private字段
field.set(bean, value);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
} /**
* 为bean对象的属性注入值
*/
private void injectObject() {
for(BeanDefinition beanDefinition : beanDefines){
Object bean = sigletons.get(beanDefinition.getId());
if(bean!=null){
try {
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for(PropertyDefinition propertyDefinition : beanDefinition.getPropertys()){
for(PropertyDescriptor properdesc : ps){
if(propertyDefinition.getName().equals(properdesc.getName())){
Method setter = properdesc.getWriteMethod();//获取属性的setter方法 ,private
if(setter!=null){
Object value = null;
if(propertyDefinition.getRef()!=null && !"".equals(propertyDefinition.getRef().trim())){
value = sigletons.get(propertyDefinition.getRef());
}else{
value = ConvertUtils.convert(propertyDefinition.getValue(), properdesc.getPropertyType());
}
setter.setAccessible(true);
setter.invoke(bean, value);//把引用对象注入到属性
}
break;
}
}
}
} catch (Exception e) {
}
}
}
}
/**
* 完毕bean的实例化
*/
private void instanceBeans() {
for(BeanDefinition beanDefinition : beanDefines){
try {
if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim()))
sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());
} catch (Exception e) {
e.printStackTrace();
}
} }
/**
* 读取xml配置文件
* @param filename
*/
private void readXML(String filename) {
SAXReader saxReader = new SAXReader();
Document document=null;
try{
URL xmlpath = this.getClass().getClassLoader().getResource(filename);
document = saxReader.read(xmlpath);
Map<String,String> nsMap = new HashMap<String,String>();
nsMap.put("ns","http://www.springframework.org/schema/beans");//增加命名空间
XPath xsub = document.createXPath("//ns:beans/ns:bean");//创建beans/bean查询路径
xsub.setNamespaceURIs(nsMap);//设置命名空间
List<Element> beans = xsub.selectNodes(document);//获取文档下全部bean节点
for(Element element: beans){
String id = element.attributeValue("id");//获取id属性值
String clazz = element.attributeValue("class"); //获取class属性值
BeanDefinition beanDefine = new BeanDefinition(id, clazz);
XPath propertysub = element.createXPath("ns:property");
propertysub.setNamespaceURIs(nsMap);//设置命名空间
List<Element> propertys = propertysub.selectNodes(element);
for(Element property : propertys){
String propertyName = property.attributeValue("name");
String propertyref = property.attributeValue("ref");
String propertyValue = property.attributeValue("value");
PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyref, propertyValue);
beanDefine.getPropertys().add(propertyDefinition);
}
beanDefines.add(beanDefine);
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 获取bean实例
* @param beanName
* @return
*/
public Object getBean(String beanName){
return this.sigletons.get(beanName);
}
}

实现注解用的类型:@XjjResource
XjjResource.java
package junit.test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface XjjResource {
public String name() default "";
}

BeanDefinition.java

package junit.test;

import java.util.ArrayList;
import java.util.List; public class BeanDefinition {
private String id;
private String className;
private List<PropertyDefinition> propertys = new ArrayList<PropertyDefinition>(); 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> getPropertys() {
return propertys;
} public void setPropertys(List<PropertyDefinition> propertys) {
this.propertys = propertys;
}
}

PropertyDefinition.java

package junit.test;

public class PropertyDefinition {
private String name;
private String ref;
private String value; public String getValue() {
return value;
} public void setValue(String value) {
this.value = value;
} public PropertyDefinition(String name, String ref, String value) {
this.name = name;
this.ref = ref;
this.value = value;
} 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;
} }

PersonServiceBean.java对PersonDao进行注解方式注入

package xjj.service.impl;

import junit.test.XjjResource;
import xjj.dao.PersonDao;
import xjj.service.PersonService; public class PersonServiceBean implements PersonService {
@XjjResource private PersonDao personDao;
private String name; public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
} public PersonServiceBean(){} public PersonServiceBean(PersonDao personDao, String name) {
this.personDao = personDao;
this.name = name;
} public void save(){
//System.out.println(name);
personDao.add();
}
}

beans.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-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:annotation-config/>
<bean id="personDaoxxxx" class="xjj.dao.impl.PersonDaoBean"></bean>
<bean id="personService" class="xjj.service.impl.PersonServiceBean">
</bean>
</beans>

SpringTest2.java

package junit.test;

import org.junit.BeforeClass;
import org.junit.Test; import xjj.service.PersonService;
public class SpringTest2 { @BeforeClass
public static void setUpBeforeClass() throws Exception {
} @Test public void instanceSpring(){ XjjClassPathXMLApplicationContext ctx = new XjjClassPathXMLApplicationContext("beans.xml");
PersonService personService = (PersonService)ctx.getBean("personService");
personService.save(); }
}

模拟结果:成功注入了PersonDaoBean










Spring2.5学习3.2_编码剖析@Resource注解的实现原理的更多相关文章

  1. (转)编码剖析@Resource注解的实现原理

    http://blog.csdn.net/yerenyuan_pku/article/details/52860046 上文我们已经学会使用@Resource注解注入属性.学是学会了,但也仅限于会使用 ...

  2. Spring(八)编码剖析@Resource注解的实现原理

    配置文件beans2.xml <?xml version="1.0" encoding="UTF-8"? > <beans xmlns=&qu ...

  3. Spring、Spring依赖注入与编码剖析Spring依赖注入的原理

    Spring依赖注入 新建PersonIDao 和PersonDao底实现Save方法: public interface PersonIDao { public void save(); } pub ...

  4. (转)编码剖析Spring管理Bean的原理

    http://blog.csdn.net/yerenyuan_pku/article/details/52832434 在Spring的第一个案例中,我们已经知道了怎么将bean交给Spring容器进 ...

  5. (转)编码剖析Spring装配基本属性的原理

    http://blog.csdn.net/yerenyuan_pku/article/details/52856465 上回我们已经讲到了Spring依赖注入的第一种方式,现在我们来详解第二种方式,须 ...

  6. (转)编码剖析Spring依赖注入的原理

    http://blog.csdn.net/yerenyuan_pku/article/details/52834561 Spring的依赖注入 前面我们就已经讲过所谓依赖注入就是指:在运行期,由外部容 ...

  7. 编码剖析Spring管理bean的原理

    project目录 MyClassPathXMLApplicationContext读取xml,以及实例化bean. 因为是一开始实例化配置文件所有bean,所以需要构造器完成这些工作. packag ...

  8. Spring、编码剖析Spring管理Bean的原理

    引入dom4j jar包 1.新建Person接口和PersonBean public interface PersonIService { public void helloSpring(); } ...

  9. 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 ...

随机推荐

  1. HDU 5289 Assignment(二分+RMQ-ST)

    Assignment Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total ...

  2. [LVS] 用keepalived实现LVS NAT模式高可用性

    默认前提是LVS已经可以正常工作了. 因为是NAT模式,RS的路由要指向LVS的接口地址,所以需要一个统一的后台浮动地址,使得RS都指向这个浮动IP.否则在切换时,会导致RS回包到DOWN掉的LVS上 ...

  3. python获取目录下文件夹名称

    path = '/opt' dirs = os.listdir(path) for dir in dirs: print dir

  4. 【NOIP2009】最优贸易

    描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通 ...

  5. 命名参数和可选参数在.NET中的使用

    原文发布时间为:2011-04-25 -- 来源于本人的百度文章 [由搬家工具导入] Named and Optional Arguments class NamedExample{staticvoi ...

  6. [LeetCode] Count and Say 字符串

    The count-and-say sequence is the sequence of integers beginning as follows:1, 11, 21, 1211, 111221, ...

  7. 【Visual Studio】简单内存泄漏检测方法 解决 Detected memory leaks! 问题(转)

    原文转自 http://blog.csdn.net/u011430225/article/details/47840647 我的环境是: XP SP2.VS2003 最近在一个项目中, 程序退出后都出 ...

  8. django Modelform 使用

    前言: 为什么要用form去验证呢? 我们提交的是form表单,在看前端源码时如果检查到POST URL及我们提交的字段,如果没有验证我们是否可以直接POST数据到URL,后台并没有进行校验,直接处理 ...

  9. [Oracle] 某游戏大区DB IO负载过高分析

    某游戏大区DB IO负载过高分析 [问题] 下图信息看出机器IO负载过高, IO使用率: 平均值 50%, 峰值 98%, 业务高峰时间段(19:00-22:00)IO使用率持续80%以上. [分析] ...

  10. javascript 动态添加城市

    匿名函数的使用 createTextnode 创建文本 createElement   创建元素 appendChild     将文本或元素追加 <!DOCTYPE html> < ...