1. 程式人生 > >Spring(八)編碼剖析@Resource註解的實現原理

Spring(八)編碼剖析@Resource註解的實現原理

配置檔案beans2.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"
>
<!-- 把針對註解的容器注射到Spring容器中 --> <context:annotation-config /> <bean id="personDaoxx" class="test.spring.dao.impl.PersonDaoBean" /> <!-- <bean id="personService" class="test.spring.service.impl.PersonServiceBean4"></bean> --> <bean id="personService"
class="test.spring.service.impl.PersonServiceBean3">
</bean> </beans>
package test.spring.dao;

public interface PersonDao {

    public abstract void add();

}
package test.spring.dao.impl;

import test.spring.dao.PersonDao;


public class PersonDaoBean implements PersonDao {

    @Override
public void add(){ System.out.println("執行PersonDaoBean裡的test1()方法"); } }
package test.spring.service;

public interface PersonService2 {

    public abstract void save();
}
package test.spring.service.impl;

import test.spring.dao.PersonDao;
import test.spring.jnit.AnnotationTest;
import test.spring.service.PersonService2;

public class PersonServiceBean3 implements PersonService2 {

    private PersonDao personDao;
    private String name;

    public PersonServiceBean3() {

    }

    public PersonServiceBean3(PersonDao personDao, String name) {
        this.personDao = personDao;
        this.name = name;
    }

    public PersonDao getPersonDao() {
        return personDao;
    }

    @AnnotationTest
    public void setPersonDao(PersonDao personDao) {
        this.personDao = personDao;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void save() {
        // TODO Auto-generated method stub
        personDao.add();
        // System.out.println(name);
    }
}
package test.spring.jnit;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.dom4j.Element;

//選擇在執行期
@Retention(RetentionPolicy.RUNTIME)
// 指定註解只能用在欄位和方法上
@Target({ ElementType.FIELD, ElementType.METHOD })
public @interface AnnotationTest {

    public String name() default "";
}
package test.spring.jnit;

import java.beans.IntrospectionException;
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;

import test.spring.entity.Bean2;
import test.spring.entity.Property;

public class AnnotationInjectTest {

    private List<Bean2> beanDefines = new ArrayList<Bean2>();
    private Map<String, Object> singletons = new HashMap<String, Object>();

    public AnnotationInjectTest(String filename) {
        this.readXML(filename);
        this.instanceBeans();
        this.injectObject();
        this.annotationInject();
    }

    private void annotationInject() {
        // TODO Auto-generated method stub
        for (String beanName : singletons.keySet()) {
            Object bean = singletons.get(beanName);
            if (bean != null) {
                try {
                    PropertyDescriptor[] pDescriptors = Introspector
                            .getBeanInfo(bean.getClass())
                            .getPropertyDescriptors();
                    for (PropertyDescriptor propertyDescriptor : pDescriptors) {
                        Method setter = propertyDescriptor
                                .getWriteMethod();
                        if (setter != null
                                && setter
                                        .isAnnotationPresent(AnnotationTest.class)) {
                            AnnotationTest aTest = setter
                                    .getAnnotation(AnnotationTest.class);
                            Object value = null;
                            if (aTest.name() != null
                                    && !"".equals(aTest.name())) {
                                value = singletons.get(aTest.name());
                                setter.setAccessible(true);
                                try {
                                    setter.invoke(bean, value);
                                } catch (Exception e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                            } else {
                                value = singletons.get(propertyDescriptor
                                        .getName());
                                if (value == null) {
                                    for (String key : singletons.keySet()) {
                                        if (propertyDescriptor
                                                .getPropertyType()
                                                .isAssignableFrom(
                                                        singletons.get(key)
                                                                .getClass())) {
                                            value = singletons.get(key);
                                            break;
                                        }
                                    }
                                }
                            }
                            setter.setAccessible(true);
                            try {
                                setter.invoke(bean, value);
                            } catch (Exception e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                    }
                    Field[] fields = bean.getClass().getDeclaredFields();
                    for (Field field : fields) {
                        if (field.isAnnotationPresent(AnnotationTest.class)) {
                            AnnotationTest aTest = field
                                    .getAnnotation(AnnotationTest.class);
                            Object value = null;
                            if (aTest.name() != null
                                    && !"".equals(aTest.name())) {
                                value = singletons.get(aTest.name());

                            } else {
                                value = singletons.get(field.getName());
                                if (value == null) {
                                    for (String key : singletons.keySet()) {
                                        if (field.getType().isAssignableFrom(
                                                singletons.get(key).getClass())) {
                                            value = singletons.get(key);
                                            break;
                                        }
                                    }
                                }
                            }
                            field.setAccessible(true);
                            try {
                                field.set(bean, value);
                            } catch (IllegalArgumentException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            } catch (IllegalAccessException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                    }
                } catch (IntrospectionException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 為bean物件的屬性注入值
     */
    private void injectObject() {
        for (Bean2 beanDefinition : beanDefines) {
            Object bean = singletons.get(beanDefinition.getId());
            if (bean != null) {
                try {
                    PropertyDescriptor[] ps = Introspector.getBeanInfo(
                            bean.getClass()).getPropertyDescriptors();
                    for (Property propertyDefinition : beanDefinition
                            .getProperties()) {
                        for (PropertyDescriptor properdesc : ps) {
                            if (propertyDefinition.getName().equals(
                                    properdesc.getName())) {
                                java.lang.reflect.Method setter = properdesc
                                        .getWriteMethod();// 獲取屬性的setter方法
                                                            // ,private
                                if (setter != null) {
                                    Object value = null;
                                    if (propertyDefinition.getRef() != null
                                            && !"".equals(propertyDefinition
                                                    .getRef().trim())) {
                                        value = singletons
                                                .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 (Bean2 beanDefinition : beanDefines) {
            try {
                if (beanDefinition.getClassPath() != null
                        && !"".equals(beanDefinition.getClassPath().trim()))
                    singletons.put(beanDefinition.getId(),
                            Class.forName(beanDefinition.getClassPath())
                                    .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屬性值
                Bean2 beanDefine = new Bean2(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");
                    Property propertyDefinition = new Property(propertyName,
                            propertyref, propertyValue);
                    beanDefine.getProperties().add(propertyDefinition);
                }
                beanDefines.add(beanDefine);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 獲取bean例項
     * 
     * @param beanName
     * @return
     */
    public Object getBean(String beanName) {
        return this.singletons.get(beanName);
    }

}
package test.spring.jnit;

import org.junit.Test;
import test.spring.service.PersonService2;

public class SpringTest4 {

    @Test
    public void testAnnotationInject() {
        AnnotationInjectTest applicationContext = new AnnotationInjectTest(
                "beans2.xml");
        PersonService2 personService = (PersonService2) applicationContext
                .getBean("personService");
        personService.save();
    }

}

待續