首先看一下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. transform总结

    1. 用jquery的css方法获取transform得到的是矩阵matrix,不利于获取translate的值, 优先使用dom.style.webKitTransform进行transform的读 ...

  2. 使用PropTypes进行类型检测

    PropTypes 是react提供的用于检验数据类型的typechecking,避免应用越来越大的时候出现意料之外的bug class Greeting extends React.Componen ...

  3. vue-router 页面切换后保持在页面顶部而不是保持原先的滚动位置的办法

    vue-router有提供一个方法scrollBehavior,它可以使切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样. 这个功能只在 HTML5 history 模 ...

  4. hdoj 4293 Groups

    Groups Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  5. pat 甲级 Public Bike Management

    Public Bike Management (30) 题目描述 There is a public bike service in Hangzhou City which provides grea ...

  6. Union和Concat的区别,以及它们的速度 (C# Linq)

    原文发布时间为:2011-06-29 -- 来源于本人的百度文章 [由搬家工具导入] Union 会去重复后合并。而Contact不去重直接合并。 所以Contact当然比较快了。所以如果你不用去重的 ...

  7. Repeater用ul li,一行显示多条数据

    原文发布时间为:2009-08-26 -- 来源于本人的百度文章 [由搬家工具导入] .rep {         width:680px;         float:left;         l ...

  8. webRTC实战总结

    前言 前段时间一直在忙一个基于WebRTC的PC和移动端双向视频的项目.第一次接触webRTC,难免遇到了许多问题,比如:webRTC移动端兼容性检测,如何配置MediaStreamConstrain ...

  9. glRectf(-0.5f, -0.5f, 0.5f, 0.5f)

    http://bbs.csdn.net/topics/370049656 x向右,y向上时OPENGL坐标系,z向屏幕外表示正方向(-0.5,-0.5)是左下角坐标,(0.5,0.5)是右上角坐标,, ...

  10. 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---30

    以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下: