Spring(八)編碼剖析@Resource註解的實現原理
阿新 • • 發佈:2019-01-01
配置檔案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();
}
}
待續