这几天重新把传智播客的黎活明的Spring2.5的教程学习了一遍,跟着上面的解析Spring的过程跟着制作了一个简单的Spring IOC和Spring AOP,先在贴上来给大家参考一下。
1:管理Bean和依赖注入 配制文件bean.xml格式如下模板所示:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.ganggang.com/beans"> <bean id="personDao" class="com.ganggang.dao.impl.PersonDaoImpl"> </bean> <bean id="personService" class="com.ganggang.service.impl.PersonServiceImpl"> <property name="no" value="0704685003"/> </bean> </beans>
用一个名为XmlApplication的类从bean.xml中读取相应的bean的配制信息并根据需要返回想要实例化的bean的实例对象。
public class XmlApplication { private List<BeanDefinition> beans=new ArrayList<BeanDefinition>(); private Map<String,Object> objs=new HashMap<String, Object>(); public XmlApplication(String file){ this.readXml(file); this.instance(); this.annotationInject(); this.injectObject(); ................ } }
XmlApplication对象实例化时,先用readXml函数读取bean.xml中的bean配置信息,将每个bean实例化成BeanDefinition对象并存储在名为beans的链表中,BeanDefinition定义如下:
public class BeanDefinition { private String id; private String className; private List<PropertyDefinition> propertys=new ArrayList<PropertyDefinition>(); public BeanDefinition(String id, String className) { this.id = id; this.className = className; } ...........getter和setter方法 }
BeanDefinition中的propertys用来表示每个bean中的属性,每个属性即是一个PropertyDefinition型对象,PropertyDefinition定义如下:
public class PropertyDefinition { private String name; private String ref; private String value; public PropertyDefinition(String name, String ref,String value) { this.name = name; this.ref = ref; this.value=value; } .................getter和setter方法 }
readXml函数的代码如下:
private void readXml(String file) { SAXReader saxReader = new SAXReader(); Document document=null; try{ URL xmlpath = this.getClass().getClassLoader().getResource(file); document = saxReader.read(xmlpath); Map<String,String> nsMap = new HashMap<String,String>(); nsMap.put("ns","http://www.ganggang.com/beans");//加入命名空间 XPath xsub = document.createXPath("//ns:beans/ns:bean");//创建beans/bean查询路径 xsub.setNamespaceURIs(nsMap);//设置命名空间 List<Element> beanss = xsub.selectNodes(document);//获取文档下所有bean节点 for(Element element: beanss){ String id = element.attributeValue("id");//获取id属性值 System.out.println(id); String clazz = element.attributeValue("class"); //获取class属性值 BeanDefinition beanDefine = new BeanDefinition(id, clazz); //开始处理property XPath propertysub=element.createXPath("ns:property"); propertysub.setNamespaceURIs(nsMap); List<Element> props=propertysub.selectNodes(element); for(Element e:props){ String name=e.attributeValue("name"); String ref=e.attributeValue("ref"); String val=e.attributeValue("value"); PropertyDefinition propertyDefinition=new PropertyDefinition(name,ref,val); beanDefine.getPropertys().add(propertyDefinition); System.out.println("name:"+name+";value:"+val); } //除了你property完毕 beans.add(beanDefine); } }catch(Exception e){ e.printStackTrace(); } }
然后,XmlApplication再调用instance方法实例化beans中的bean,并将每个bean对象存储在map型的objs中,objs中的key即为每个bean的id。
private void instance() { for(BeanDefinition bean:beans){ try { objs.put(bean.getId(), Class.forName(bean.getClassName()).newInstance()); System.out.println(bean.getId()); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
最后进行依赖注入,本程序同时支持注解注入和xml配制文件注入,根据实际需要选择注入方式。其中annotationInject函数执行注解注入,injectObject函数执行配制文件注入。代码如下:
private void annotationInject() { for(String beanName:objs.keySet()){ Object bean=objs.get(beanName); if(bean!=null){ try { PropertyDescriptor[] ps=Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); for(PropertyDescriptor properdesc:ps){ Method setter=properdesc.getWriteMethod(); if(setter!=null&&setter.isAnnotationPresent(Resource.class)){ Resource resource=setter.getAnnotation(Resource.class); Object value=null; if(resource.name()!=null&&!"".equals(resource.name())){ value=objs.get(resource.name()); }else{ value=objs.get(properdesc.getName()); if(value==null){ for(String key:objs.keySet()){ if(properdesc.getPropertyType().isAssignableFrom(objs.get(key).getClass())){ value=objs.get(key); break; } } } } setter.setAccessible(true); setter.invoke(bean, value); } } Field[] fields= bean.getClass().getDeclaredFields(); for(Field field:fields){ if(field.isAnnotationPresent(Resource.class)){ Resource resource=field.getAnnotation(Resource.class); Object value=null; if(resource.name()!=null&&!"".equals(resource.name())){ value=objs.get(resource.name()); }else{ value=objs.get(field.getName()); if(value==null){ for(String key:objs.keySet()){ if(field.getType().isAssignableFrom(objs.get(key).getClass())){ value=objs.get(key); break; } } } } field.setAccessible(true); field.set(bean, value); } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } private void injectObject() { for(BeanDefinition beanDefinition:beans){ Object bean=objs.get(beanDefinition.getId()); if(bean!=null){ try { PropertyDescriptor[] ps=Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); for(PropertyDefinition propertyDefinition:beanDefinition.getPropertys()){ for(PropertyDescriptor properdesc:ps){ if(propertyDefinition.getName().equals(properdesc.getName())){ Method setter= properdesc.getWriteMethod(); if(setter!=null){ Object value=null; if(propertyDefinition.getRef()!=null&&!"".equals(propertyDefinition.getRef().trim())){ value=objs.get(propertyDefinition.getRef()); }else{ value=ConvertUtils.convert(propertyDefinition.getValue(), properdesc.getPropertyType()); } setter.setAccessible(true); setter.invoke(bean, value); } break; } } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
注入函数遍历beans中的每一个bean,如果其中有相应的property需要注入,就从objs中取得相应的实例对象注入。
XmlApplication含有一个获取相应bean的实力的函数,名为getObj,代码如下:
public Object getObj(String id){ return objs.get(id); }
您只需在bean.xml中配制相应的bean就可以实例化一个XmlApplication对象调用getObj函数控制反转出相应的Bean的实例。
2.动态代理实现AOP
有两种,JDKProxy实现动态代理和CGLib实现。
JDKProxy实现的代码如下:
public class JDKProxyFactory implements InvocationHandler{ private Object targetObject; public Object createProxyInstance(Object targetObject){ this.targetObject=targetObject; return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(), this.targetObject.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { PersonServiceBean bean=(PersonServiceBean)this.targetObject; Object result=null; if(bean.getUser()!=null){ result=method.invoke(targetObject, args); } return result; } }
CGLib实现的代码如下:
public class CGligProxyFactory implements MethodInterceptor{ private Object targetObject; public Object createProxyInstance(Object targetObject){ this.targetObject=targetObject; Enhancer enhancer=new Enhancer(); enhancer.setSuperclass(this.targetObject.getClass()); enhancer.setCallback(this); return enhancer.create(); } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { PersonServiceBean bean=(PersonServiceBean)this.targetObject; Object result=null; if(bean.getUser()!=null){ result=methodProxy.invoke(targetObject, args); } return null; }
相关推荐
Spring 解析,特详细的
从spring的源码角度分析spring的ioc,aop,springmvc等spring技术 值得你看
spring源码解析的,里面介绍了springIoc,springAop,用xmind来整理的,内容清晰,不一定完全正确,仅供参考,如有问题,希望大家私我,我修改,这个免费给大家修改了
Spring的jar包解析
在spring环境中通过component-scan配置处理自定义java注解
Spring 源代码解析Spring 源代码解析Spring 源代码解析Spring 源代码解析Spring 源代码解析Spring 源代码解析Spring 源代码解析Spring 源代码解析Spring 源代码解析Spring 源代码解析Spring 源代码解析Spring 源代码...
Spring源码解析
模拟spring框架的ioc功能,简单实用的实现,高效。
Spring源代码解析(一):IOC容器 Spring源代码解析(二):IoC容器在Web容器中的启动 Spring源代码解析(三):Spring JDBC Spring源代码解析(四):Spring MVC Spring源代码解析(五):Spring AOP获取Proxy Spring源...
Spring源码深度解析第二版
spring源码解析。使用xmind进行代码整理。包含ioc,aop,tr相关代码部分。
主要给大家介绍了Spring Batch读取txt文件并写入数据库的方法,SpringBatch 是一个轻量级、全面的批处理框架。这里我们用它来实现文件的读取并将读取的结果作处理,处理之后再写入数据库中的功能。需要的朋友可以...
Spring源码解析Spring源码解析Spring源码解析Spring源码解析Spring源码解析
《Spring技术内幕:深入解析Spring架构与设计原理(第2版)》从源代码的角度对Spring的内核和各个主要功能模块的架构、设计和实现原理进行了深入剖析。你不仅能从本书中参透Spring框架的出色架构和设计思想,还能从...
NULL 博文链接:https://bjameng.iteye.com/blog/1468057
spring源码解析 spring spring教程 spring深入
Spring源代码解析1:IOC容器.doc Spring源代码解析2:IoC容器在Web容器中的启动.doc Spring源代码解析3:Spring JDBC .doc Spring源代码解析4:Spring MVC .doc Spring源代码解析5:Spring AOP获取Proxy .doc Spring...
Spring技术内幕:深入解析Spring架构与设计原理.pdf