• Spring解析实践


    这几天重新把传智播客的黎活明的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;  
        }  
    

      

  • 相关阅读:
    【Git】常规操作指令
    SourceTree Push 代码报错:remote: Support for password authentication was removed on April 26, 2022.
    【Vue】事件修饰符
    leetcode 周赛290
    如何通过接口工具,和复制浏览器的请求参数,来模拟调式接口
    Unreal 输入系统 解析
    Poco API精讲之 等待 wait
    Poco API精讲之点击click()、long_click()、double_click()
    Airtest的前世今生
    2022年最新版本QT安装教程
  • 原文地址:https://www.cnblogs.com/qingwengang/p/5972594.html
Copyright © 2020-2023  润新知