package junit.test; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.InvalidXPathException; import org.dom4j.XPath; import org.dom4j.io.SAXReader; public class ItcastClassPathXMLApplicationContext { private List<BeanDefinition> beanDefines=new ArrayList<BeanDefinition>(); private Map<String,Object> singtions=new HashMap<String,Object>(); public ItcastClassPathXMLApplicationContext(String filename){ this.readXML(filename); instanceBeans(); } private void instanceBeans(){ for(BeanDefinition bd:beanDefines){ try { if(bd.getId()!=null || bd.getClassName()!=null) singtions.put(bd.getId(), Class.forName(bd.getClassName()).newInstance()); } catch (Exception e) { e.printStackTrace(); } } } @SuppressWarnings({ "null", "unused", "unchecked" }) private void readXML(String filename) { System.out.println("read"+filename); SAXReader saxReader=new SAXReader(); Document document=null; try { URL xmlPath=this.getClass().getClassLoader().getResource(filename); // System.out.println(xmlPath); document = saxReader.read(xmlPath); Map<String, String> nsMap=new HashMap<String, String>(); nsMap.put("ns","http://www.springframework.org/schema/beans"); //加入命名空间 System.out.println(nsMap+"nsmap"); XPath xsub = document.createXPath("//ns:beans/ns:bean"); //创建beans/bean查询路径 System.out.println("xsub"+xsub); xsub.setNamespaceURIs(nsMap); //设置命名空间 List<Element> beans=xsub.selectNodes(document); for(Element e:beans){ String id=e.attributeValue("id"); //获取id属性 String clazz=e.attributeValue("class"); //获取class属性 BeanDefinition beanDefine=new BeanDefinition(id,clazz); beanDefines.add(beanDefine); } } catch (Exception e) { e.printStackTrace(); } } public Object getBean(String beanName){ return singtions.get(beanName); } }
package cn.itcast.service.impl; import cn.itcast.service.IPersonService; public class PersonServiceBean implements IPersonService { /* (non-Javadoc) * @see cn.itcast.service.impl.IPersonService#save() */ @Override public void save(){ System.out.println("我是Save()方法"); } }
package junit.test; import org.junit.BeforeClass; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.itcast.service.IPersonService; public class SpringTest { // static ApplicationContext ctx=null; ItcastClassPathXMLApplicationContext ctx=new ItcastClassPathXMLApplicationContext("beans.xml"); @BeforeClass public static void setUpBeforeClass() throws Exception { // ctx=new ClassPathXmlApplicationContext(new String[]{"bean.xml"}); // System.out.println(ctx); } @Test public void test(){ IPersonService personService = (IPersonService)ctx.getBean("personService"); System.out.println(personService); personService.save(); } }
bean.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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean" /> </beans>
注解类
package junit.test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** 元注解@Target,@Retention,@Documented,@Inherited * * @Target 表示该注解用于什么地方,可能的 ElemenetType 参数包括: * ElemenetType.CONSTRUCTOR 构造器声明 * ElemenetType.FIELD 域声明(包括 enum 实例) * ElemenetType.LOCAL_VARIABLE 局部变量声明 * ElemenetType.METHOD 方法声明 * ElemenetType.PACKAGE 包声明 * ElemenetType.PARAMETER 参数声明 * ElemenetType.TYPE 类,接口(包括注解类型)或enum声明 * * @Retention 表示在什么级别保存该注解信息。可选的 RetentionPolicy 参数包括: * RetentionPolicy.SOURCE 注解将被编译器丢弃 * RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃 * RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。 * * @Documented 将此注解包含在 javadoc 中 * * @Inherited 允许子类继承父类中的注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.METHOD}) public @interface ItcastResource { public String name() default ""; //此注解有个name属性,类似@Resource(name="personDao") }
注解处理器方法
private void annotationInject(){ for(String beanName:singletons.keySet()){ Object bean=singletons.get(beanName); if(bean!=null){ try { PropertyDescriptor[] pds=Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); for(PropertyDescriptor pd:pds){ Method setter=pd.getWriteMethod(); //得到这个属性的setter方法 if(setter!=null && setter.isAnnotationPresent(ItcastResource.class)){ //查看setter方法上没有ItcastResource注解 ItcastResource resource=setter.getAnnotation(ItcastResource.class); //取得这个注解 Object value=null; if(resource.name()!=null && !"".equals(resource.name())){ //如果注解的名称属性不为空 value=singletons.get(resource.name()); //取得这个bean实例 setter.invoke(bean, value); }else{ //如果注解名称属性为空 value=singletons.get(pd.getName()); //直接得到这个属性bean if(value==null){ //如果得不到这个属性的bean for(String key:singletons.keySet()){ //则遍历所有bean名称,找到类型相匹配的 if(pd.getPropertyType().isAssignableFrom(singletons.get(key).getClass())){ value=singletons.get(key); break; } } } } setter.setAccessible(true); setter.invoke(bean, value); //把得到的依赖bean通过setter注入到bean } } 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=singletons.get(resource.name()); //取得这个bean实例 }else{ //如果注解名称属性为空 value=singletons.get(field.getName()); //直接得到这个属性bean if(value==null){ //如果得不到这个属性的bean for(String key:singletons.keySet()){ //则遍历所有bean名称,找到类型相匹配的 if(field.getType().isAssignableFrom(singletons.get(key).getClass())){ value=singletons.get(key); break; } } } } field.setAccessible(true); //允许访问私有字段 field.set(bean, value); } } } catch (Exception e) { e.printStackTrace(); } } } }