zoukankan      html  css  js  c++  java
  • 7 -- Spring的基本用法 -- 4... 使用 Spring 容器:Spring 容器BeanFactory、ApplicationContext;ApplicationContext 的国际化支持;ApplicationContext 的事件机制;让Bean获取Spring容器;Spring容器中的Bean

        7.4 使用 Spring 容器

          Spring 有两个核心接口:BeanFactory 和 ApplicationContext,其中ApplicationContext 是 BeanFactory 的子接口。它们都可代表 Spring 容器,Spring 容器是生成 Bean 实例的工厂,并管理容器中的Bean。

          Java 程序面向接口编程,无须关心 Bean 实例的实现类;但 Spring 容器负责创建 Bean 实例,因此必须精确知道每个 Bean 实例的实现类,故Spring 配置文件必须指定 Bean 实例的实现类。

          7.4.1 Spring 容器

            Spring 容器最基本的接口就是BeanFactory。BeanFactory 负责配置、创建、管理Bean,它有一个子接口:ApplicationContext,因此也被称为Spring上下文。Spring 容器还负责管理Bean 与 Bean 之间的依赖关系。

            BeanFactory 接口包含如下几个基本方法。

              boolean containsBean(String name):判断Spring容器是否包含id为name 的Bean 实例。

              <T> T getBean(Class<T> requiredType):获取Spring容器中属于requiredType类型的、唯一的Bean实例。

              Object getBean(String name):返回容器id为name的Bean实例。

              <T> T getBean(String name,Class requiredType):返回容器中id为name,并且类型为requiredType的Bean。

              Class<?> getType(String name):返回容器中id为name的Bean实例的类型。

            BeanFactory 常用的实现类是DefaultListableBeanFactory。

            ApplicationContext 常用的实现类是FileSystemXmlApplicationContext、ClassPathXmlApplicationContext 和 AnnotationConfigApplicationContext。

            如果在Web应用中使用Spring容器,则通常有XmlWebApplicationContext、AnnotationConfigWebApplicationContext两个实现类。

            创建BeanFactory实例时,应该提供XML配置文件作为参数,XML配置文件通常使用Resource对象传入。

            Resource接口是Spring提供的资源访问接口,通过使用该接口,Spring能以简单、透明的方式访问磁盘、类路径以及网络上的资源。

            大部分Java EE应用,可在启动Web应用时自动加载ApplicationContext实例,接收Spring管理的Bean无须知道ApplicationContext的存在,一样可以利用ApplicationContext的管理。

            对于独立的应用程序,可通过如下方法实例化BeanFactory。

    //        搜索类加载路径下的beans.xml 文件创建Resource对象
            Resource isr = new ClassPathResource("beans.xml");
    //        创建默认的BeanFactory容器
            DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    //        让默认的BeanFactory容器加载isr对应的XML配置文件
            new XmlBeanDefinitionReader(beanFactory).loadBeanDefinitions(isr);

            或者采用如下代码来创建BeanFactory:

    //        搜索文件系统的当前路径下的beans.xml 文件创建Resource对象
            Resource isr = new FileSystemResource("beans.xml");
    //        创建默认的BeanFactory容器
            DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    //        让默认的BeanFactory容器加载isr对应的XML配置文件。
            new XmlBeanDefinitionReader(beanFactory).loadBeanDefinitions(isr);

            如果应用需要加载多个配置文件来创建Spring容器,则应该采用BeanFactory的子接口ApplicationContext来创建BeanFactory的实例。

            ApplicationContext接口包含FileSystemXmlApplicationContext和ClassPathXmlApplicationContext两个常用的实现类。

            如果需要同时加载多个XML配置文件来创建Spring容器,则可以采用如下方式:

    //        以类加载路径下的Beans.xml、service.xml文件创建ApplicationContext
            ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml","service.xml");

            当然也可支持从文件系统的相对路径或绝对路径来搜索配置文件,只要使用FileSystemXmlApplicationContext即可。

    //        以类加载路径下的Beans.xml、service.xml文件创建ApplicationContext
            ApplicationContext ctx = new FileSystemXmlApplicationContext("beans.xml","service.xml");

           7.4.2 使用ApplicationContext

            大部分时候使用ApplicationContext实例作为容器,因此也把Spring容器称为Spring上下文。ApplicationContext是BeanFactory接口的子接口,它增强了BeanFactory的功能。

            ApplicationContext允许以声明式方式操作容器,无须手动创建它。可利用ContextLoader的支持类,在Web应用启动时自动创建ApplicationContext。当然也可采用编程方式创建ApplicationContext。

            除了提供BeanFactory所支持的全部功能外,ApplicationContext还有如下额外的功能。

              ApplicationContext默认会预初始化所有singleton Bean,也可通过配置取消预初始化。

              ApplicationContext继承MessageSource接口,因此提供国际化支持。

              资源访问,比如访问URL文件。

              事件机制。

              同时加载多个配置文件。

              以声明式方式启动并创建Spring容器。

            配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.springframework.org/schema/beans"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    
        <!-- 如果不加任何特殊的配置,该Bean默认是singleton行为的 -->
        <bean id="chinese" class="edu.pri.lime._7_4_2.bean.Person">
            <property name="test" value="孙悟空"/>
        </bean>
    
    </beans>

            Class: Person

    package edu.pri.lime._7_4_2.bean;
    
    public class Person {
        
        public Person(){
            System.out.println("==正在执行Person无参数的构造器==");
        }
        
        public void setTest(String name){
            System.out.println("正在调用setTest()方法,传入参数为:" + name);
        }
    }

            Class: TestBean

    package edu.pri.lime._7_4_2.test;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestBean {
    
        public static void main(String[] args){
            ApplicationContext ctx = new ClassPathXmlApplicationContext("app_7_4_2.xml");
        }
    }

            Console:

    ==正在执行Person无参数的构造器==
    正在调用setTest()方法,传入参数为:孙悟空

            配置文件<bean.../>如果没有任何特殊配置,该Bean就是singleton Bean,ApplicationContext会在容器初始化完成后,自动调用Person类的构造器创建chinese Bean,并以“孙悟空”作为参数去调用chinese Bean的setTest()方法。

            如果使用BeanFactory作为容器,BeanFactory不会预初始化容器中的Bean。

            为了阻止Spring容器预初始化容器中的singleton Bean,可以为<bean.../>元素指定lazy-init="true",该属性用于阻止容器预初始化该Bean。

       <!-- 阻止容器预初始化Bean -->
        <bean id="chinese" class="edu.pri.lime._7_4_2.bean.Person" lazy-init="true">
            <property name="test" value="孙悟空"/>
        </bean>

          7.4.3 ApplicationContext 的国际化支持

            ApplicationContext接口继承了MessageSource接口,因此具有国际化功能。

            MessageSource接口中定义的两个用于国际化的方法:

              String getMessage(String code,Object[] args,Locale loc)

              String getMessage(String code,Object[] args,String default,Locale loc)

            ApplicationContext 正是通过这两个方法来完成国际化的,当程序创建ApplicationContext容器时,Spring自动查找配置文件中名为messageSource的Bean实例,一旦找到这个Bean实例,上述两个方法的调用就被委托给该messageSource Bean。如果没有该Bean,ApplicationContext会查找其父容器中的messageSource Bean;如果找到,它将被作为messageSource Bean 使用。如果无法找到messageSource Bean,系统将会创建一个空的StaticMessageSource Bean ,该Bean能就收上述两个方法的调用。

            在Spring中配置messageSource Bean是通常使用ResourceBundleMessageSource类。

            message_zh_CN.properties:

    hello=u6B22u8FCEu4F60,{0}
    now=u73B0u5728u65F6u95F4u662FuFF1A{0}

            message_en_US.properties:

    hello=welcome,{0}
    now=now is:{0}

            app_7_4_3.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.springframework.org/schema/beans"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    
        <bean id="messageSource"
            class="org.springframework.context.support.ResourceBundleMessageSource">
            <!-- 驱动Spring调用messageSource Bean的setBasenames()方法, 
            该方法需要一个数组参数,使用list元素配置多个数组元素 -->
            <property name="basenames">
                <list>
                    <value>message</value>
                    <!-- 如果有多个资源文件,全部列在此处 -->
                </list>
            </property>
        </bean>
    </beans>

            SpringTest:

    package edu.pri.lime._7_4_3.main;
    
    import java.util.Date;
    import java.util.Locale;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class SpringTest {
    
        public static void main(String[] args){
    //        实例化ApplicationContext
            ApplicationContext ctx = new ClassPathXmlApplicationContext("app_7_4_3.xml");
    //        使用getMessage()方法获取本地化消息。
    //        Locale的getDefault()方法获取本地化消息
    //        Gets the current value of the default locale for the specified Category for this instance of the Java Virtual Machine.
    //        Category used to represent the default locale for formatting dates, numbers, and/or currencies.
            String hello = ctx.getMessage("hello", new String[]{"孙悟空"},Locale.getDefault(Locale.Category.FORMAT));
            String now = ctx.getMessage("now", new Object[]{new Date()},Locale.getDefault(Locale.Category.FORMAT));
    //        打印出两条本地化信息
            System.out.println(hello);
            System.out.println(now);
            
            System.out.println("----------------------------");
            Locale enUs = new Locale("en", "US");
            String hello_ = ctx.getMessage("hello", new String[]{"lime"}, enUs);
            String now_ = ctx.getMessage("now", new Object[]{new Date()}, enUs);
            System.out.println(hello_);
            System.out.println(now_);
        }
    }

            Spring 的国际化支持,其实是简历在Java程序国际化的基础之上的。其核心思路都是将程序中需要实现国际化的信息写入资源文件,而代码中仅仅使用相应的各信息的Key。

          7.4.4 ApplicationContext 的事件机制

            ApplicationContext的事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext的事件处理。

            如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被触发。

            Spring的事件框架有如下两个重要成员:

              ApplicationEvent:容器事件,必须由ApplicationContext发布。

              ApplicationListener:监听器,可由容器中的任何监听器Bean担任。

            Spring的事件机制与所有的事件机制有基本相似,它们都需要由事件源、事件和事件监听器组成。只是此处的事件源是ApplicationContext,且事件必须由Java程序显式触发。

             Class:EmailEvent

    package edu.pri.lime._7_4_4.bean;
    
    import org.springframework.context.ApplicationEvent;
    
    //只要一个Java类继承了ApplicationEvent基类,那该对象就可作为Spring容器的容器事件(观察者模式:主题)
    public class EmailEvent extends ApplicationEvent {
    
        private static final long serialVersionUID = 1L;
        
        private String address;
        private String text;
        
        public EmailEvent(Object source) {
            super(source);
            // TODO Auto-generated constructor stub
        }
    
    //    初始化全部成员变量的构造器
        public EmailEvent(Object source, String address, String text) {
            super(source);
            this.address = address;
            this.text = text;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public String getText() {
            return text;
        }
    
        public void setText(String text) {
            this.text = text;
        }
    }

            Class : MyOtherEvent

    package edu.pri.lime._7_4_4.bean;
    
    import org.springframework.context.ApplicationEvent;
    
    public class MyOtherEvent extends ApplicationEvent {
        private static final long serialVersionUID = -2196975742599078369L;
    
        public MyOtherEvent(Object source) {
            super(source);
            // TODO Auto-generated constructor stub
        }
    }

            Class : EmailNotifier

    package edu.pri.lime._7_4_4.bean;
    
    import org.springframework.context.ApplicationEvent;
    import org.springframework.context.ApplicationListener;
    
    //容器事件的监听器类必须实现ApplicationListener接口(观察者模式:观察者)
    public class EmailNotifier implements ApplicationListener {
    
    
    //    该方法会在容器发生任何事件时都会自动触发
        public void onApplicationEvent(ApplicationEvent event) {
    //        只处理EmailEvent,模拟发送email通知
            if(event instanceof EmailEvent){
                EmailEvent emailEvent = (EmailEvent) event;
                System.out.println("EmailEvent " + event);
                System.out.println("需要发送邮件的接收地址  " + emailEvent.getAddress());
                System.out.println("需要发送邮件的邮件正文  " + emailEvent.getText());
            }else{
    //            其他事件不作任何处理
                System.out.println("其他事件 :" + event);
            }
        }
    
    }

            XML :app_7_4_4.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.springframework.org/schema/beans"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
        <!-- 配置监听器 -->
        <!-- 只要在Spring中配置一个实现了ApplicationListener接口的Bean,Spring容器就会把这个Bean当成容器事件的事件监听器 -->
        <bean class="edu.pri.lime._7_4_4.bean.EmailNotifier" />
    </beans>

            Class : SpringTest

    package edu.pri.lime._7_4_4.main;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import edu.pri.lime._7_4_4.bean.EmailEvent;
    import edu.pri.lime._7_4_4.bean.MyOtherEvent;
    
    public class SpringTest {
    
        public static void main(String[] args){
    //        当系统创建Spring容器、加载Spring容器时会自动触发容器事件,容器时间监听器可以监听到这些事件。
            ApplicationContext ctx = new ClassPathXmlApplicationContext("app_7_4_4.xml");
    //        创建一个ApplicationEvent对象
            EmailEvent emailEvent = new EmailEvent("test","zzulime@outlook.com","this is a test");
    //        调用ApplicationContext的pulishEvent()方法来主动触发容器事件。
            ctx.publishEvent(emailEvent);
            
            System.out.println("---------------");
            
            MyOtherEvent myOtherEvent = new MyOtherEvent("myOtherEvent");
            ctx.publishEvent(myOtherEvent);
        }
    }

            Console :

    十二月 31, 2016 11:58:05 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@56cbfb61: startup date [Sat Dec 31 23:58:05 CST 2016]; root of context hierarchy
    十二月 31, 2016 11:58:06 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [app_7_4_4.xml]
    其他事件 :org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.support.ClassPathXmlApplicationContext@56cbfb61: startup date [Sat Dec 31 23:58:05 CST 2016]; root of context hierarchy]
    EmailEvent edu.pri.lime._7_4_4.bean.EmailEvent[source=test]
    需要发送邮件的接收地址  zzulime@outlook.com
    需要发送邮件的邮件正文  this is a test
    ---------------
    其他事件 :edu.pri.lime._7_4_4.bean.MyOtherEvent[source=myOtherEvent]

            监听器不仅监听到程序所触发的事件,也监听到容器内置的事件。实际上,如果开发者需要在Spring容器初始化、销毁时回调自定义方法,就可以通过上面的事件监听器来实现。

            如果Bean希望发布容器事件,则该Bean必须先获得对Spring容器的引用。为了让Bean获得对Spring容器的引用,可让Bean类实现ApplicationContextAware或BeanFactoryAware接口。

            Spring 提供了如下几个内置事件:

              ⊙ ContextRefreshedEvent : ApplicationContext容器初始化或刷新触发该事件,此处的初始化是指,所有的Bean被成功加载,后处理的Bean被检测并激活,所有的singleton Bean 被预实例化,ApplicationContext容器已就绪可用。

              ⊙ ContextStartedEvent : 当使用ConfigurableApplicationContext (ApplicationContext的子接口)接口的start()方法启动ApplicationContext容器时触发该事件。容器管理生命周期的Bean实例将获得一个指定的启动信号,这在经常需要停止后重新启动的场合比较常见。

              ⊙ ContextClosedEvent : 当使用ConfigurableApplicationContext(ApplicationContext的子接口)接口的close()方法关闭ApplicationContext容器时触发该事件。

              ⊙ ContextStoppedEvent : 当使用ConfigurableApplicationContext(ApplicationContext的子接口)接口的stop()方法使ApplicationContext停止时触发该事件。此处的“停止”意味着容器管理生命周期的Bean实例将获得一个指定的停止信号,被停止的Spring容器可再次调用start()方法重新启动。

              ⊙ RequestHandledEvent : Web相关的事件,只能应用于使用DispatcherServlet的Web应用中。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。

              ⊙ SessionConnectedEvent : 用于WebSocket功能服务

              ⊙ SessionConnectEvent :用于WebSocket功能服务

              ⊙ SessionDisconnectEvent :用于WebSocket功能服务

          7.4.5 让Bean获取Spring容器

            在Web应用中,Spring容器通常采用声明式方式配置产生:开发者只要在web.xml文件中配置一个Listener,该Listener将会负责初始化Spring容器,前端MVC框架可以直接调用Spring容器中的Bean,无须访问Spring容器本身。在这种情况下,容器中的Bean处于容器管理下,无须主动访问容器,只需接收容器的依赖注入即可。

            在某些特殊的情况下,Bean需要实现某个功能(比如该Bean需要输出国际化消息,或者giantBean需要想Spirng容器发布事件......),但该功能必须借助于Spring容器才能实现,此时就必须让该Bean先获取Spring容器,然后借助于Spring容器来实现该功能。

            为了让Bean获取它所在的Spring容器,可以让该Bean实现BeanFactoryAware接口,并覆写唯一的方法setBeanFacotry(BeanFactory beanFactory)。

              setBeanFactory(BeanFactory beanFactory) : beanFactory参数指向创建它的BeanFactory。

            该方法将由Spring调用,Spring调用该方法时会将Spring容器作为参数传入该方法。

            与BeanFactoryAware接口类似的有ApplicationContextAware接口,实现该接口的Bean需要实现setApplicationContext(ApplicationContext applicationContext)方法,该方法有Spring来调用,当Spring容器调用该方法时,它会把自身作为参数传入该方法。

             Class : Person

    package edu.pri.lime._7_4_5.bean;
    
    import java.util.Date;
    import java.util.Locale;
    
    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    
    /* 国际化功能需要借助于Spring容器来实现,因此程序就需要让Person类实现ApplicationContextAware接口。
     */
    public class Person implements ApplicationContextAware {
    
    //    将BeanFactory容器以成员变量保存
        private ApplicationContext ctx;
    //    Spring 容器会检测容器中所有的Bean,如果发现某个Bean实现了ApplicationContextAware接口,
    //    Spring容器会在创建该Bean后,自动调用该方法,调用该方法时,会将容器本身最为参数传给该方法
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.ctx = applicationContext;
        }
    
    //    借助ApplicationContext容器的getMessage方法获取国际化消息
        public void sayHi(String name){
            System.out.println(ctx.getMessage("hello", new String[]{name}, Locale.getDefault(Locale.Category.FORMAT)));
        }
    }

            property :message_zh_CN.properties

    hello=u6B22u8FCEu4F60,{0}
    now=u73B0u5728u65F6u95F4u662FuFF1A{0}

            property :message_en_US.properties

    hello=welcome,{0}
    now=now is:{0}

            XML : app_7_4_5.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.springframework.org/schema/beans"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    
        <!-- 加载容器国际化所需要的语言资源文件 -->
        <bean id="messageSource"
            class="org.springframework.context.support.ResourceBundleMessageSource">
            <property name="basenames">
                <list>
                    <value>message</value>
                </list>
            </property>
        </bean>
        <!-- Spring容器会检测容器中所有的Bean,如果发现某个Bean实现了ApplicationContextAware接口, 
        Spring容器会在创建该Bean之后,自动调用该Bean的setApplicationContext()方法, 
            并将容器本身最为参数传给该方法。 -->
        <bean id="person" class="edu.pri.lime._7_4_5.bean.Person" />
    
    </beans>

            Class : SpringTest

    package edu.pri.lime._7_4_5.main;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import edu.pri.lime._7_4_5.bean.Person;
    
    public class SpringTest {
    
        public static void main(String[] args){
            ApplicationContext ctx = new ClassPathXmlApplicationContext("app_7_4_5.xml");
            Person per = ctx.getBean("person",Person.class);
            per.sayHi("lime");
        }
    }

        7.5 Spring容器中的Bean

          7.5.1 Bean的基本定义和Bean别名

            <beans.../>元素是Spring配置文件的根元素,该元素可以指定如下属性:

              default-lazy-init : 指定该<beans.../> 元素下配置的所有Bean默认的延迟初始化行为。

              default-merge : 指定该<beans.../> 元素下配置的所有Bean默认的merge行为。

              default-autowire : 指定该<beans.../> 元素下配置的所有Bean 默认的自动装配行为。

              default-autowire-candidates: : 指定该<beans.../> 元素下配置的所有Bean 默认是否作为自动装配的候选Bean。

              default-init-method : 指定该<beans.../> 元素下配置的所有Bean 默认的初始化方法。

              default-destroy-method : 指定该<beans.../> 元素下配置的所有Bean 默认的回收方法。

            <beans.../>元素下所能指定的属性都可以在每个<bean.../>子元素中指定----将属性名去掉default即可。区别是:为<bean.../>指定的这些属性,只对特定Bean起作用;如果在<beans.../>元素下指定这些属性,这些属性将会对<beans.../>包含的所有Bean都起作用。当二者所指定的属性不一致时,<bean.../>下指定的属性会覆盖<beans.../>下指定的属性。

            <bean.../>元素的id属性具有唯一性,而且是一个真正的XML ID 属性,因此其他XML元素在引用id时,可以利用XML解析器的验证功能。

            指定别名有两种方式:

            ⊙ 定义<bean.../>元素时通过name属性指定别名;如果需要为Bean实例指定多个别名,则可以在name属性中使用逗号、冒号或者空格来分隔多个别名,后面通过任一别名即可访问该Bean实例。

            ⊙ 通过<alias.../>元素为已有的Bean指定别名。

              <alias name="" alias=""/> name:指定一个Bean实例的标识名,表明将为该Bean实例指定别名;alias:指定一个别名。

        <bean id="person" class="edu.pri.lime._7_4_5.bean.Person" name="chinese,lime,oracle"/>
        <alias name="person" alias="jackson"/>
        <alias name="person" alias="tomcat"/>

      啦啦啦

  • 相关阅读:
    MYSQL 之 JDBC(十三):处理事务
    MYSQL 之 JDBC(十四):批量处理JDBC语句提高处理效率
    MYSQL 之 JDBC(十五):数据库连接池
    MYSQL 之 JDBC(十六): DBUtils
    MYSQL 之 JDBC(十七): 调用函数&存储过程
    Android初级教程理论知识(第八章网络编程二)
    android6.0SDK 删除HttpClient的相关类的解决方法
    iOS下WebRTC音视频通话(三)-音视频通话
    love~LBJ,奥布莱恩神杯3
    Android简易实战教程--第二话《两种进度条》
  • 原文地址:https://www.cnblogs.com/ClassNotFoundException/p/6238851.html
Copyright © 2011-2022 走看看