spring中註解的實現原理,幫助理解@autowired @resource區別
阿新 • • 發佈:2019-01-07
package com.yt.annotation; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; /** * @Description: spring中的註解原理 * @ClassName: ClassPathXMLApplicationContext * @Project: spring-aop * @Author: zxf * @Date: 2011-6-3 */ public class ClassPathXMLApplicationContext { Logger log = Logger.getLogger(ClassPathXMLApplicationContext.class); List<BeanDefine> beanList = new ArrayList<BeanDefine>(); Map<String, Object> sigletions = new HashMap<String, Object>(); public ClassPathXMLApplicationContext(String fileName) { //讀取配置檔案中管理的bean this.readXML(fileName); //例項化bean this.instancesBean(); //註解處理器 this.annotationInject(); } /** * 讀取Bean配置檔案 * @param fileName * @return */ @SuppressWarnings("unchecked") public void readXML(String fileName) { Document document = null; SAXReader saxReader = new SAXReader(); try { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); document = saxReader.read(classLoader.getResourceAsStream(fileName)); Element beans = document.getRootElement(); for (Iterator<Element> beansList = beans.elementIterator(); beansList.hasNext();) { Element element = beansList.next(); BeanDefine bean = new BeanDefine( element.attributeValue("id"), element.attributeValue("class")); beanList.add(bean); } } catch (DocumentException e) { log.info("讀取配置檔案出錯...."); } } /** * 例項化Bean */ public void instancesBean() { for (BeanDefine bean : beanList) { try { sigletions.put(bean.getId(), Class.forName(bean.getClassName()).newInstance()); } catch (Exception e) { log.info("例項化Bean出錯..."); } } } /** * 註解處理器 * 如果註解ZxfResource配置了name屬性,則根據name所指定的名稱獲取要注入的例項引用, * 如果註解ZxfResource;沒有配置name屬性,則根據屬性所屬型別來掃描配置檔案獲取要 * 注入的例項引用 * */ public void annotationInject(){ for(String beanName:sigletions.keySet()){ Object bean = sigletions.get(beanName); if(bean!=null){ this.propertyAnnotation(bean); this.fieldAnnotation(bean); } } } /** * 處理在set方法加入的註解 * @param bean 處理的bean */ public void propertyAnnotation(Object bean){ try { //獲取其屬性的描述 PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); for(PropertyDescriptor proderdesc : ps){ //獲取所有set方法 Method setter = proderdesc.getWriteMethod(); //判斷set方法是否定義了註解 if(setter!=null && setter.isAnnotationPresent(ZxfResource.class)){ //獲取當前註解,並判斷name屬性是否為空 ZxfResource resource = setter.getAnnotation(ZxfResource.class); String name =""; Object value = null; if(resource.name()!=null&&!"".equals(resource.name())){ //獲取註解的name屬性的內容 name = resource.name(); value = sigletions.get(name); }else{ //如果當前註解沒有指定name屬性,則根據型別進行匹配 for(String key : sigletions.keySet()){ //判斷當前屬性所屬的型別是否在配置檔案中存在 if(proderdesc.getPropertyType().isAssignableFrom(sigletions.get(key).getClass())){ //獲取型別匹配的例項物件 value = sigletions.get(key); break; } } } //允許訪問private方法 setter.setAccessible(true); //把引用物件注入屬性 setter.invoke(bean, value); } } } catch (Exception e) { log.info("set方法註解解析異常.........."); } } /** * 處理在欄位上的註解 * @param bean 處理的bean */ public void fieldAnnotation(Object bean){ try { //獲取其全部的欄位描述 Field[] fields = bean.getClass().getFields(); for(Field f : fields){ if(f!=null && f.isAnnotationPresent(ZxfResource.class)){ ZxfResource resource = f.getAnnotation(ZxfResource.class); String name =""; Object value = null; if(resource.name()!=null&&!"".equals(resource.name())){ name = resource.name(); value = sigletions.get(name); }else{ for(String key : sigletions.keySet()){ //判斷當前屬性所屬的型別是否在配置檔案中存在 if(f.getType().isAssignableFrom(sigletions.get(key).getClass())){ //獲取型別匹配的例項物件 value = sigletions.get(key); break; } } } //允許訪問private欄位 f.setAccessible(true); //把引用物件注入屬性 f.set(bean, value); } } } catch (Exception e) { log.info("欄位註解解析異常.........."); } } /** * 獲取Map中的對應的bean例項 * @param beanId * @return */ public Object getBean(String beanId) { return sigletions.get(beanId); } public static void main(String[] args) { ClassPathXMLApplicationContext path = new ClassPathXMLApplicationContext( "configAnnotation.xml"); UserServiceImpl userService =(UserServiceImpl)path.getBean("userService"); userService.show(); } }