`

七 编码剖析@Resource注解的实现原理

 
阅读更多
七 编码剖析@Resource注解的实现原理

ItcastResource.java

view plaincopy to clipboardprint?
01.package junit.test;   
02.  
03.import java.lang.annotation.ElementType;   
04.import java.lang.annotation.Retention;   
05.import java.lang.annotation.RetentionPolicy;   
06.import java.lang.annotation.Target;   
07.  
08.@Retention(RetentionPolicy.RUNTIME)   
09.@Target({ElementType.FIELD, ElementType.METHOD})   
10.public @interface ItcastResource {   
11.    public String name() default "";   
12.}  
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 ItcastResource {
	public String name() default "";
}


PropertyDefinition .java

view plaincopy to clipboardprint?
01.package junit.test;   
02.  
03.public class PropertyDefinition {   
04.    private String name;   
05.    private String ref;   
06.    private String value;   
07.       
08.    public String getValue() {   
09.        return value;   
10.    }   
11.  
12.    public void setValue(String value) {   
13.        this.value = value;   
14.    }   
15.  
16.    public PropertyDefinition(String name, String ref, String value) {   
17.        this.name = name;   
18.        this.ref = ref;   
19.        this.value = value;   
20.    }   
21.       
22.    public String getName() {   
23.        return name;   
24.    }   
25.    public void setName(String name) {   
26.        this.name = name;   
27.    }   
28.    public String getRef() {   
29.        return ref;   
30.    }   
31.    public void setRef(String ref) {   
32.        this.ref = ref;   
33.    }   
34.       
35.}  
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;
	}
	
}
 

BeanDefinition.java

view plaincopy to clipboardprint?
01.package junit.test;   
02.  
03.import java.util.ArrayList;   
04.import java.util.List;   
05.  
06.public class BeanDefinition {   
07.    private String id;   
08.    private String className;   
09.    private List<PropertyDefinition> propertys = new ArrayList<PropertyDefinition>();   
10.       
11.    public BeanDefinition(String id, String className) {   
12.        this.id = id;   
13.        this.className = className;   
14.    }   
15.    public String getId() {   
16.        return id;   
17.    }   
18.    public void setId(String id) {   
19.        this.id = id;   
20.    }   
21.    public String getClassName() {   
22.        return className;   
23.    }   
24.    public void setClassName(String className) {   
25.        this.className = className;   
26.    }   
27.    public List<PropertyDefinition> getPropertys() {   
28.        return propertys;   
29.    }   
30.    public void setPropertys(List<PropertyDefinition> propertys) {   
31.        this.propertys = propertys;   
32.    }   
33.       
34.}  
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;
	}
	
}
 

ItcastClassPathXMLApplicationContext.java

view plaincopy to clipboardprint?
01.package junit.test;   
02.  
03.import java.beans.Introspector;   
04.import java.beans.PropertyDescriptor;   
05.import java.lang.reflect.Field;   
06.import java.lang.reflect.Method;   
07.import java.net.URL;   
08.import java.util.ArrayList;   
09.import java.util.HashMap;   
10.import java.util.List;   
11.import java.util.Map;   
12.  
13.import org.apache.commons.beanutils.ConvertUtils;   
14.import org.dom4j.Document;   
15.import org.dom4j.Element;   
16.import org.dom4j.XPath;   
17.import org.dom4j.io.SAXReader;   
18.  
19./**  
20. * 传智传客版容器  
21. *  
22. */  
23.public class ItcastClassPathXMLApplicationContext {   
24.    private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();   
25.    private Map<String, Object> sigletons = new HashMap<String, Object>();   
26.       
27.    public ItcastClassPathXMLApplicationContext(String filename){   
28.        this.readXML(filename);   
29.        this.instanceBeans();   
30.        this.annotationInject();   
31.        this.injectObject();   
32.    }   
33.    /**  
34.     * 通过注解实现注入依赖对象  
35.     */  
36.    private void annotationInject() {   
37.        for(String beanName : sigletons.keySet()){   
38.            Object bean = sigletons.get(beanName);   
39.            if(bean!=null){   
40.                try {   
41.                    PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();   
42.                    for(PropertyDescriptor properdesc : ps){   
43.                        Method setter = properdesc.getWriteMethod();//获取属性的setter方法   
44.                        if(setter!=null && setter.isAnnotationPresent(ItcastResource.class)){   
45.                            ItcastResource resource = setter.getAnnotation(ItcastResource.class);   
46.                            Object value = null;   
47.                            if(resource.name()!=null && !"".equals(resource.name())){   
48.                                value = sigletons.get(resource.name());   
49.                            }else{   
50.                                value = sigletons.get(properdesc.getName());   
51.                                if(value==null){   
52.                                    for(String key : sigletons.keySet()){   
53.                                        if(properdesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())){   
54.                                            value = sigletons.get(key);   
55.                                            break;   
56.                                        }   
57.                                    }   
58.                                }                                  
59.                            }   
60.                            setter.setAccessible(true);   
61.                            setter.invoke(bean, value);//把引用对象注入到属性   
62.                        }   
63.                    }   
64.                    Field[] fields = bean.getClass().getDeclaredFields();   
65.                    for(Field field : fields){   
66.                        if(field.isAnnotationPresent(ItcastResource.class)){   
67.                            ItcastResource resource = field.getAnnotation(ItcastResource.class);   
68.                            Object value = null;   
69.                            if(resource.name()!=null && !"".equals(resource.name())){   
70.                                value = sigletons.get(resource.name());   
71.                            }else{   
72.                                value = sigletons.get(field.getName());   
73.                                if(value==null){   
74.                                    for(String key : sigletons.keySet()){   
75.                                        if(field.getType().isAssignableFrom(sigletons.get(key).getClass())){   
76.                                            value = sigletons.get(key);   
77.                                            break;   
78.                                        }   
79.                                    }   
80.                                }                                  
81.                            }   
82.                            field.setAccessible(true);//允许访问private字段   
83.                            field.set(bean, value);   
84.                        }   
85.                    }   
86.                } catch (Exception e) {   
87.                    e.printStackTrace();   
88.                }   
89.            }   
90.        }   
91.    }   
92.  
93.    /**  
94.     * 为bean对象的属性注入值  
95.     */  
96.    private void injectObject() {   
97.        for(BeanDefinition beanDefinition : beanDefines){   
98.            Object bean = sigletons.get(beanDefinition.getId());   
99.            if(bean!=null){   
100.                try {   
101.                    PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();   
102.                    for(PropertyDefinition propertyDefinition : beanDefinition.getPropertys()){   
103.                        for(PropertyDescriptor properdesc : ps){   
104.                            if(propertyDefinition.getName().equals(properdesc.getName())){   
105.                                Method setter = properdesc.getWriteMethod();//获取属性的setter方法 ,private   
106.                                if(setter!=null){   
107.                                    Object value = null;   
108.                                    if(propertyDefinition.getRef()!=null && !"".equals(propertyDefinition.getRef().trim())){   
109.                                        value = sigletons.get(propertyDefinition.getRef());   
110.                                    }else{   
111.                                        value = ConvertUtils.convert(propertyDefinition.getValue(), properdesc.getPropertyType());   
112.                                    }   
113.                                    setter.setAccessible(true);   
114.                                    setter.invoke(bean, value);//把引用对象注入到属性   
115.                                }   
116.                                break;   
117.                            }   
118.                        }   
119.                    }   
120.                } catch (Exception e) {   
121.                }   
122.            }   
123.        }   
124.    }   
125.    /**  
126.     * 完成bean的实例化  
127.     */  
128.    private void instanceBeans() {   
129.        for(BeanDefinition beanDefinition : beanDefines){   
130.            try {   
131.                if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim()))   
132.                    sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());   
133.            } catch (Exception e) {   
134.                e.printStackTrace();   
135.            }   
136.        }   
137.           
138.    }   
139.    /**  
140.     * 读取xml配置文件  
141.     * @param filename  
142.     */  
143.    private void readXML(String filename) {   
144.           SAXReader saxReader = new SAXReader();      
145.            Document document=null;      
146.            try{   
147.             URL xmlpath = this.getClass().getClassLoader().getResource(filename);   
148.             document = saxReader.read(xmlpath);   
149.             Map<String,String> nsMap = new HashMap<String,String>();   
150.             nsMap.put("ns","http://www.springframework.org/schema/beans");//加入命名空间   
151.             XPath xsub = document.createXPath("//ns:beans/ns:bean");//创建beans/bean查询路径   
152.             xsub.setNamespaceURIs(nsMap);//设置命名空间   
153.             List<Element> beans = xsub.selectNodes(document);//获取文档下所有bean节点    
154.             for(Element element: beans){   
155.                String id = element.attributeValue("id");//获取id属性值   
156.                String clazz = element.attributeValue("class"); //获取class属性值           
157.                BeanDefinition beanDefine = new BeanDefinition(id, clazz);   
158.                XPath propertysub =  element.createXPath("ns:property");   
159.                propertysub.setNamespaceURIs(nsMap);//设置命名空间   
160.                List<Element> propertys = propertysub.selectNodes(element);   
161.                for(Element property : propertys){                     
162.                    String propertyName = property.attributeValue("name");   
163.                    String propertyref = property.attributeValue("ref");   
164.                    String propertyValue = property.attributeValue("value");   
165.                    PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyref, propertyValue);   
166.                    beanDefine.getPropertys().add(propertyDefinition);   
167.                }   
168.                beanDefines.add(beanDefine);   
169.             }    
170.            }catch(Exception e){      
171.                e.printStackTrace();   
172.            }   
173.    }   
174.    /**  
175.     * 获取bean实例  
176.     * @param beanName  
177.     * @return  
178.     */  
179.    public Object getBean(String beanName){   
180.        return this.sigletons.get(beanName);   
181.    }   
182.}  
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;

/**
 * 传智传客版容器
 *
 */
public class ItcastClassPathXMLApplicationContext {
	private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
	private Map<String, Object> sigletons = new HashMap<String, Object>();
	
	public ItcastClassPathXMLApplicationContext(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(ItcastResource.class)){
							ItcastResource resource = setter.getAnnotation(ItcastResource.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(ItcastResource.class)){
							ItcastResource resource = field.getAnnotation(ItcastResource.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);
	}
}
 

实际上也就是通过了反射技术来构造对象并且赋值,只是用到了注解的方法,并且利用@interface来构造自定义的注解类型。

 

分享到:
评论

相关推荐

    编码剖析@Resource注解的实现原理

    这篇文章将深入探讨`@Resource`注解的工作原理,以及它如何与Spring的IoC(Inversion of Control,控制反转)容器协同工作。 首先,让我们理解`@Resource`的基本用法。当在类的字段或方法上使用`@Resource`时,...

    Spring学习笔记(6)----编码剖析Spring依赖注入的原理

    本篇学习笔记将深入剖析Spring依赖注入的原理,通过源码分析帮助我们理解这一核心机制。 首先,依赖注入允许我们解耦组件之间的关系,使得各个组件可以独立地进行开发、测试和维护。在Spring中,DI主要通过两种方式...

    ejb3.0实例教程SourceCode

    3. **依赖注入(Dependency Injection)**:EJB 3.0支持JSR 330标准的依赖注入,如@Autowired和@Resource注解,这使得对象之间的关系可以通过配置而非硬编码来建立,提高了代码的可读性和可维护性。 4. **接口驱动...

    spring 原理与代码分析

    本篇文章将深入探讨Spring框架的工作原理和代码分析,帮助你更好地理解和掌握其精髓。 1. **依赖注入(DI)**: - DI是Spring的核心特性,它允许对象之间的依赖关系在运行时通过配置文件或注解来管理,而不是硬...

    Spring 3.0 源码

    Spring 3.0进一步强化了这一特性,支持了基于注解的依赖注入,如`@Autowired`、`@Qualifier`和`@Resource`,使得配置更加简洁。 2. **AOP(面向切面编程)**: Spring 3.0增强了AOP支持,允许开发者定义和执行横切...

    Hibernate注解编程实例

    ### Hibernate注解编程实例 #### Hibernate注解简介 在Java领域中,Hibernate作为一个非常流行的ORM(Object Relational Mapping,...希望本文能够帮助您更好地理解和掌握Hibernate注解编程的核心概念及其实现方式。

    spring2.5源码分析

    Spring的核心特性之一是依赖注入,它允许开发者通过配置文件或注解来管理对象间的依赖关系,而非硬编码。在Spring 2.5中,DI进一步强化,支持了基于注解的配置,使得代码更简洁、可读性更强。 2. **AOP(Aspect-...

    第七章 Spring4 继承、依赖、引用

    分析Spring的源码有助于深入理解其工作原理。例如,了解`DefaultListableBeanFactory`如何解析和管理Bean的定义,以及`ApplicationContext`如何加载和初始化Bean,这些都能帮助我们更好地设计和优化应用程序。 5. ...

    尚学堂_Spring_0700_IOC_Collections

    在实际开发中,我们还需要了解如何处理集合的泛型类型,Spring如何处理集合元素的依赖排序,以及如何使用`@Lazy`注解实现延迟初始化等高级特性。同时,对于Map类型的集合注入,我们可以通过键值对来指定元素,这对于...

    Java架构面试专题(含答案)和学习笔记-1

    - **依赖注入**:理解IoC和DI,以及@Autowired、@Resource等注解的使用。 - **AOP**:面向切面编程的原理,以及如何实现切面和通知。 8. **数据库相关**: - **SQL优化**:索引原理,如何编写高效的SQL语句,...

    spring框架学习

    - **注入注解标记使用方法**:使用`@Autowired`、`@Resource`等注解来自动装配Bean。 - **AOP注解标记使用方法**:使用`@Aspect`、`@Before`等注解来定义和使用切面。 #### 八、Spring对数据访问技术的支持 - **...

    SpringBoot+Spring+MyBatis-51问-面试用

    了解每个功能的目的,实践编码,逐步深入理解其原理。 5. **SpringBoot 启动过程** - 加载配置类。 - 分析类并获取配置信息。 - 存储配置信息并创建BeanDefinition对象。 - 根据BeanDefinition构建Bean对象,...

    spring 3.1的 源码

    在分析Spring 3.1源码时,可以深入了解这些特性的实现原理,以及Spring如何通过模块化设计来实现高内聚、低耦合。这将有助于开发者更好地理解和使用Spring框架,同时也能提升问题排查和性能优化的能力。对于想要深入...

    spring boot创建项目,实现同域名下单点登录源码

    - 同域名下实现SSO,一般不会遇到跨域问题,但需要注意的是,如果应用分布在不同的子域名下,需要配置CORS(Cross-Origin Resource Sharing)策略,确保浏览器允许不同子域名之间的通信。 7. **安全性考虑**: - ...

    code: J2EE Core Patterns

    9. **资源注入(Dependency Injection)**:Java EE的注解如`@EJB`, `@Resource`等,实现了依赖注入,简化了组件之间的关联和配置。 10. **服务定位器模式**:虽然现代Java EE推荐使用CDI(Contexts and Dependency...

    SSH框架面试题.pdf

    Spring通过AOP代理实现了面向切面编程的功能,允许开发者通过配置或注解的方式将这些横切关注点织入到正常的业务逻辑中,而不必在业务代码中显式实现。 24. **解释Spring MVC的控制器(Controller)** Spring MVC...

    spring源代码中文详解版

    Spring框架的源代码分析主要集中在它的核心特性——控制反转(IOC)容器上...通过源代码分析,我们可以了解到Spring如何高效地管理对象生命周期,以及如何通过XML或注解实现依赖注入,从而提升软件的灵活性和可维护性。

Global site tag (gtag.js) - Google Analytics