spring深入源码2 简单实现ioc机制 注解形式

上一篇文章 我用了xml形式 实现自己简单版的spring ioc依赖注入  这节主要利用注解形式实现 和上集内容一样 只是加了读取注解的方法。

DAO接口

public interface PersonDao {  
      
        public void add();  
      
    }

实现类

package cn.leam.dao.impl;  
      
    import cn.leam.dao.PersonDao;  
      
    public class PersonDaoBean implements PersonDao {  
        public void add(){  
            System.out.println("执行add()方法");  
        }  
    }

服务接口

public interface PersonService {  
      
        public void save();  
      
    }
 

服务实现类

public class PersonServiceBean implements PersonService {  
        @LeamResource private PersonDao personDao;  
          
        public PersonDao getPersonDao() {  
            return personDao;  
        }  
      
        public void setPersonDao(PersonDao personDao) {  
            this.personDao = personDao;  
        }  
          
        public void save(){  
            personDao.add();  
        }  
    }
<?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="personDao" class="cn.leam.dao.impl.PersonDaoBean"></bean>  
              <bean id="personService" class="cn.leam.service.impl.PersonServiceBean">  
               <!--这里把xml定义的属性去掉 我们使用注解获取 
                  <property name="personDao" ref="personDao"></property>  -->
              </bean>  
    </beans>

下面模拟spring对xml配置的类进行实例化

存放属性的对象

public class prosDefinition {  
        private String name;  
        private String ref;  
          
        public ProsDefinition(String name, String ref) {  
            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;  
        }  
          
    }

存放bean的 对象

public class Definition {  
        private String id;  
        private String className;  
        private List<ProsDefinition> propertys = new ArrayList<ProsDefinition>();  
          
        public Definition(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;  
        }  
          
    }

加上注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface LeamResource {
	public String name() default "";
}
 

这里是关键点  所有代码都在这里    使用dom4j 解析xml文件中的bean  并获取id和class  再判断元素中是否有引用元素对其一并获取出来存放才Map中 利用java反射一个一个进行实例化

/** 
     * 学习版容器 
     * 
     */  
    public class LeamClassPathXMLApplicationContext {  
        private List<Definition> beanDefines = new ArrayList<Definition>();  
        private Map<String, Object> sigletons = new HashMap<String, Object>();  
          
        public LeamClassPathXMLApplicationContext(String filename){  
            this.readXML(filename);  
            this.instanceBeans();  
            this.annotationInject();
            this.injectObject();  
        }  
        /** 
         * 为bean对象的属性注入值 
         */  
        private void injectObject() {  
            for(Definition beanDefinition : beanDefines){  
                Object bean = sigletons.get(beanDefinition.getId());  
                if(bean!=null){  
                    try {  
                        PropertyDescriptor[] ps = 
                    Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();  
                 for(ProsDefinition propertyDefinition : beanDefinition.getPropertys()){  
                            for(PropertyDescriptor properdesc : ps){  
                              if(propertyDefinition.getName().equals(properdesc.getName())){  
                   Method setter = properdesc.getWriteMethod();//获取属性的setter方法
                                    if(setter!=null){  
                      Object value = sigletons.get(propertyDefinition.getRef());  
                                        setter.setAccessible(true);  
                                        setter.invoke(bean, value);//把引用对象注入到属性  
                                    }  
                                    break;  
                                }  
                            }  
                        }  
                    } catch (Exception e) {  
                    }  
                }  
            }  
        }  
        /** 
         * 完成bean的实例化 
         */  
        private void instanceBeans() {  
            for(Definition 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属性值          
                    Definition beanDefine = new Definition(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");  
    ProsDefinition propertyDefinition = new ProsDefinition(propertyName, propertyref);  
                        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);  
        }  
    }  



/**
	 * 通过注解实现注入依赖对象
	 */
	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方法
                                        //如果是用了注解 将在set方法注入进去
					if(setter!=null && setter.isAnnotationPresent(LeamResource.class)){
					LeamResource resource = setter.getAnnotation(LeamResource.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(LeamResource.class)){
					LeamResource resource = field.getAnnotation(LeamResource.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();
				}
			}
		}
	}
public class SpringTest {  
      
        @BeforeClass  
        public static void setUpBeforeClass() throws Exception {  
        }  
      
        @Test public void instanceSpring(){  
            LeamClassPathXMLApplicationContext ctx = new  
                                          LeamClassPathXMLApplicationContext("beans.xml");  
            PersonService personService = (PersonService)ctx.getBean("personService");  
            personService.save();         
        }  
    }

最终输出

"执行add()方法" 说明实例化成功  否则 出现空指针异常

相关推荐