??xml version="1.0" encoding="utf-8" standalone="yes"?>BlogJava-菜毛毛技术分?/title><link>http://www.qpkxbc.shop/caizh2009/</link><description>与大家共同成?/description><language>zh-cn</language><lastBuildDate>Sat, 24 Aug 2019 08:44:36 GMT</lastBuildDate><pubDate>Sat, 24 Aug 2019 08:44:36 GMT</pubDate><ttl>60</ttl><item><title>java sax 解析 实例http://www.qpkxbc.shop/caizh2009/archive/2011/05/11/350042.html菜毛毛菜毛毛Wed, 11 May 2011 14:34:00 GMThttp://www.qpkxbc.shop/caizh2009/archive/2011/05/11/350042.htmlhttp://www.qpkxbc.shop/caizh2009/comments/350042.htmlhttp://www.qpkxbc.shop/caizh2009/archive/2011/05/11/350042.html#Feedback0http://www.qpkxbc.shop/caizh2009/comments/commentRss/350042.htmlhttp://www.qpkxbc.shop/caizh2009/services/trackbacks/350042.html 
?/strong>SAX解析XML实例
实例Q以下输?/strong>中的所有属性和标签?/strong>
package com.meixin.xml;

import java.io.File;
import java.util.HashMap;
import java.util.Vector;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class PraseXML extends DefaultHandler
{

  private Vector<String> tagName;

  private Vector<String> tagValue;

  private int step;

  // 开始解析XML文g
  public void startDocument() throws SAXException
  {
    tagName = new Vector<String>();
    tagValue = new Vector<String>();
    step = 0;
  }

  // l束解析XML文g
  public void endDocument() throws SAXException
  {
    for (int i = 0; i < tagName.size(); i++)
    {
      if (!tagName.get(i).equals("") || tagName.get(i) != null)
      {
        System.out.println("节点名称Q? + tagName.get(i));
        System.out.println("节点|" + tagValue.get(i));
      }
    }
  }

  /**
    * 在解释到一个开始元素时会调用此Ҏ.但是当元素有重复时可以自己写法来区?
    * q些重复的元?qName是什? <name:page ll=""></name:page>q样写就会抛出SAXException错误
    * 通常情况下qName{于localName
    */

  public void startElement(String uri, String localName, String qName,
      Attributes attributes) throws SAXException
  {
    // 节点名称
    tagName.add(qName);
    // 循环输出属?
    for (int i = 0; i < attributes.getLength(); i++)
    {
      // 获取属性名U?
      System.out.println("属性名Uͼ" + attributes.getQName(i));
      // 获取属性?
      System.out.println("属性|"
          + attributes.getValue(attributes.getQName(i)));
    }

  }

  /**
    * 在遇到结束标{时调用此方?
    */

  public void endElement(String uri, String localName, String qName)
      throws SAXException
  {

    step = step + 1;
  }

  /**
    * d标签里的?ch用来存放某行的xml的字W数?包括标签,初始大小?048,
    * 每解释到新的字符会把它添加到char[]里?nbsp;   * 注意,q个char字符会自q理存储的字符,
    * q不是每一行就会刷Cơchar,start,length是由xml的元素数据确定的,
    * 暂时找不到规?以后看源代码.
    *    
    * q里一个正标签Q反标签都会被执行一ơcharactersQ所以在反标{时不用获得其中的?
    */

  public void characters(char ch[], int start, int length)
      throws SAXException
  {
    // 只要当前的标{的长度一臻I值就不赋Q则反标{不被计划在?
    if (tagName.size() - 1 == tagValue.size())
    {
      tagValue.add(new String(ch, start, length));
    }
  }

  public static void main(String[] args)
  {
    String filename = "MyXml.xml";
    SAXParserFactory spf = SAXParserFactory.newInstance();
    try
    {
      SAXParser saxParser = spf.newSAXParser();
      saxParser.parse(new File(filename), new PraseXML());
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }

  public Vector getTagName()
  {
    return tagName;
  }

  public void setTagName(Vector tagName)
  {
    this.tagName = tagName;
  }

  public Vector getTagValue()
  {
    return tagValue;
  }

  public void setTagValue(Vector tagValue)
  {
    this.tagValue = tagValue;
  }

}
输出l果Q?/span>
属性名Uͼpersonid
属性|e01
属性名Uͼenable
属性|true
属性名Uͼpersonid
属性|e02
属性名Uͼenable
属性|false
属性名Uͼpersonid
属性|e03
属性名Uͼenable
属性|true
节点名称Qpeople
节点|

    
节点名称Qperson
节点|
    
节点名称Qname
节点|张三
节点名称Qtel
节点|5128
节点名称Qemail
节点|txq512@sina.com
节点名称Qperson
节点|
    
节点名称Qname
节点|meixin
节点名称Qtel
节点|5252525
节点名称Qemail
节点|wnight88@sina.com
节点名称Qperson
节点|
    
节点名称Qname
节点|yu
节点名称Qtel
节点|5389654
节点名称Qemail
节点|yu@188.net
文g内容
<?xml version="1.0" encoding="UTF-8"?>
<people>

  <person personid="e01" enable="true">
    <name>张三</name>
    <tel>5128</tel>
    <email>txq512@sina.com</email>
  </person>
    
  <person personid="e02" enable="false">
    <name>meixin</name>
    <tel>5252525</tel>
    <email>wnight88@sina.com</email>
  </person>
    
  <person personid="e03" enable="true">
    <name>yu</name>
    <tel>5389654</tel>
    <email>yu@188.net</email>
  </person>
    
</people>

http://wnight88.blog.51cto.com/512204/163197/


菜毛毛 2011-05-11 22:34 发表评论
]]>
Spring 框架的设计理念与设计模式分析http://www.qpkxbc.shop/caizh2009/archive/2011/02/15/344368.html菜毛毛菜毛毛Tue, 15 Feb 2011 08:13:00 GMThttp://www.qpkxbc.shop/caizh2009/archive/2011/02/15/344368.htmlhttp://www.qpkxbc.shop/caizh2009/comments/344368.htmlhttp://www.qpkxbc.shop/caizh2009/archive/2011/02/15/344368.html#Feedback0http://www.qpkxbc.shop/caizh2009/comments/commentRss/344368.htmlhttp://www.qpkxbc.shop/caizh2009/services/trackbacks/344368.html

介: Spring 作ؓ现在最优秀的框架之一Q已被广泛的使用Qƈ且有很多对其分析的文章。本文将从另外一个视角试囑։析出 Spring 框架的作者设?Spring 框架的骨骼架构的设计理念Q有那几个核心组ӞZ么需要这些组Ӟ它们又是如何l合在一h?Spring 的骨骼架构? Spring ? AOP Ҏ又是如何利用这些基的骨骼架构来工作的? Spring 中又使用了那些设计模式来完成它的q种设计的?它的q种设计理念对对我们以后的Y件设计有何启C?本文详l解{这些问题?/p>

Spring 的骨骼架?/strong>

Spring d有十几个lgQ但是真正核心的lg只有几个Q下面是 Spring 框架的M架构图:


?1 .Spring 框架的M架构?/font>
?1 .Spring 框架的M架构? src=

从上图中可以看出 Spring 框架中的核心lg只有三个QCore、Context ?Beans。它们构v了整?Spring 的骨骼架构。没有它们就不可能有 AOP、Web {上层的Ҏ功能。下面也主要从q三个组件入手分?Spring?/p>

Spring 的设计理?/strong>

前面介绍?Spring 的三个核心组Ӟ如果再在它们三个中选出核心的话Q那非 Beans lg莫属了,Zq样_其实 Spring 是面向 Bean 的编E(BOP,Bean Oriented ProgrammingQ,Bean ?Spring 中才是真正的主角?/p>

Bean ?Spring 中作用就?Object ?OOP 的意义一P没有对象的概念就像没有面向对象编E,Spring 中没? Bean 也就没有 Spring 存在的意义。就像一ơ演台都准备好了但是却没有演员一栗ؓ什么要 Bean q种角色 Bean 或者ؓ何在 Spring 如此重要Q这?Spring 框架的设计目标决定,Spring Z如此行Q我们用 Spring 的原因是什么,x你会发现原来 Spring 解决了一个非常关键的问题他可以让你把对象之间的依赖关p{而用配置文g来管理,也就是他的依赖注入机制。而这个注入关pd一个叫 Ioc 容器中管理,?Ioc 容器中有又是什么就是被 Bean 包裹的对象。Spring 正是通过把对象包装在 Bean 中而达到对q些对象理以及一些列额外操作的目的?/p>

它这U设计策略完全类g Java 实现 OOP 的设计理念,当然?Java 本n的设计要?Spring 复杂太多太多Q但是都是构Z个数据结构,然后Ҏq个数据l构设计他的生存环境Qƈ让它在这个环境中按照一定的规律在不停的q动Q在它们的不停运动中? 计一pd与环境或者与其他个体完成信息交换。这h来回q头x我们用到的其他框枉是大慨类似的设计理念?/p>

核心lg如何协同工作

前面?Bean ?Spring 中关键因素,?Context ?Core 又有何作用呢Q前面吧 Bean 比作一场演Z的演员的话,?Context 是q场演出的舞台背景,?Core 应该是演出的道具了。只有他们在一h能具备能演出一场好戏的最基本的条件。当然有最基本的条件还不能使这场演颖而出Q还要他表演的节目够的_? 彩,q些节目是 Spring 能提供的特色功能了?/p>

我们知道 Bean 包装的是 ObjectQ?Object 必然有数据,如何l这些数据提供生存环境就?Context 要解决的问题Q对 Context 来说他就是要发现每个 Bean 之间的关p,为它们徏立这U关pdƈ且要l护好这U关pR所?Context 是一?Bean 关系的集合,q个关系集合又叫 Ioc 容器Q一旦徏立vq个 Ioc 容器?Spring 可以ؓ你工作了。那 Core lg又有什么用武之地呢Q其?Core 是发现、徏立和l护每个 Bean 之间的关pL需要的一些列的工P从这个角度看来,Core q个lg? Util 更能让你理解?/p>

它们之间可以用下图来表示Q?/p>
?2. 三个lg关系
?2. 三个lg关系

核心lg详解

q里详l介l每个组件内部类的层ơ关p,以及它们在运行时的时序顺序。我们在使用 Spring 是应该注意的地方?/p>

Bean lg

前面已经说明?Bean lg?Spring 的重要性,下面看看 Bean q个lg式怎么设计的。Bean lg?Spring ? org.springframework.beans 包下。这个包下的所有类主要解决了三件事QBean 的定义、Bean 的创Z及对 Bean 的解析。对 Spring 的用者来说唯一需要关心的是 Bean 的创建,其他两个?Spring 在内部帮你完成了Q对你来说是透明的?/p>

Spring Bean 的创建时典型的工厂模式,他的接口?BeanFactoryQ下图是q个工厂的承层ơ关p:


?4. Bean 工厂的承关p?/font>
?4. Bean 工厂的承关p? src=

BeanFactory 有三个子c:ListableBeanFactory、HierarchicalBeanFactory ? AutowireCapableBeanFactory。但是从上图中我们可以发现最l的默认实现cL DefaultListableBeanFactoryQ他实现了所有的接口。那Z要定义这么多层次的接口呢Q查阅这些接口的源码和说明发玎ͼ每个接口 都有他用的场合Q它主要是ؓ了区分在 Spring 内部在操作过E中对象的传递和转化q程中,对对象的数据讉K所做的限制。例? ListableBeanFactory 接口表示q些 Bean 是可列表的,?HierarchicalBeanFactory 表示的是q些 Bean 是有l承关系的,也就是每?Bean 有可能有?Bean。AutowireCapableBeanFactory 接口定义 Bean 的自动装配规则。这四个接口共同定义?Bean 的集合、Bean 之间的关pR以?Bean 行ؓ?/p>

Bean 的定义主要有 BeanDefinition 描述Q如下图说明了这些类的层ơ关p:


?5. Bean 定义的类层次关系?/font>
?5. Bean 定义的类层次关系? src=

Bean 的定义就是完整的描述了在 Spring 的配|文件中你定义的 <bean/> 节点中所有的信息Q包括各U子节点。当 Spring 成功解析你定义的一?<bean/> 节点后,?Spring 的内部他p转化?BeanDefinition 对象。以后所有的操作都是对这个对象完成的?/p>

Bean 的解析过E非常复杂,功能被分的很l,因ؓq里需要被扩展的地方很多,必须保证有够的灉|性,以应对可能的变化。Bean 的解析主要就是对 Spring 配置文g的解析。这个解析过E主要通过下图中的cd成:


?6. Bean 的解析类
?6. Bean 的解析类

当然q有具体?tag 的解析这里ƈ没有列出?/p>

Context lg

Context ?Spring ?org.springframework.context 包下Q前面已l讲解了 Context lg? Spring 中的作用Q他实际上就是给 Spring 提供一个运行时的环境,用以保存各个对象的状态。下面看一下这个环境是如何构徏的?/p>

ApplicationContext ?Context 的顶U父c,他除了能标识一个应用环境的基本信息外,他还l承了五个接口,q五个接口主要是扩展?Context 的功能。下面是 Context 的类l构图:


?7. Context 相关的类l构?/font>
?7. Context 相关的类l构? src=

Q查??7 的清晰版?/font>。)

从上图中可以看出 ApplicationContext l承?BeanFactoryQ这也说明了 Spring 容器中运行的M对象? BeanQ另?ApplicationContext l承?ResourceLoader 接口Q?ApplicationContext 可以讉KCQ何外部资源,q将?Core 中详l说明?/p>

ApplicationContext 的子cM要包含两个方面:

  1. ConfigurableApplicationContext 表示?Context 是可修改的,也就是在构徏 Context 中用户可以动态添加或修改已有的配|信息,它下面又有多个子c,其中最l常使用的是可更新的 ContextQ即 AbstractRefreshableApplicationContext cR?
  2. WebApplicationContext ֐思义Q就是ؓ web 准备?Context 他可以直接访问到 ServletContextQ通常情况下,q个接口使用的少?

再往下分是按照构徏 Context 的文件类型,接着是讉K Context 的方式。这样一U一U构成了完整?Context {层次?/p>

M来说 ApplicationContext 必须要完成以下几件事Q?/p>

  • 标识一个应用环?
  • 利用 BeanFactory 创徏 Bean 对象
  • 保存对象关系?
  • 能够捕获各种事g

Context 作ؓ Spring ?Ioc 容器Q基本上整合?Spring 的大部分功能Q或者说是大部分功能的基?/p>

Core lg

Core lg作ؓ Spring 的核心组Ӟ他其中包含了很多的关键类Q其中一个重要组成部分就是定义了资源的访问方式。这U把所有资源都抽象成一个接口的方式很值得在以后的设计中拿来学习。下面就重要看一下这个部分在 Spring 的作用?/p>

下图?Resource 相关的类l构图:


?8. Resource 相关的类l构?/font>
?8. Resource 相关的类l构? src=

Q查??8 的清晰版?/font>。)

从上囑֏以看?Resource 接口装了各U可能的资源cdQ也是对用者来说屏蔽了文gcd的不同。对资源的提供者来_如何把资源包装v来交l其他h用这也是一个问题,我们看到 Resource 接口l承?InputStreamSource 接口Q这个接口中有个 getInputStream ҎQ返回的? InputStream cR这h有的资源都被可以通过 InputStream q个cL获取Q所以也屏蔽了资源的提供者。另外还有一个问题就是加载资源的问题Q也是资源的加载者要l一Q从上图中可以看个Q务是? ResourceLoader 接口完成Q他屏蔽了所有的资源加蝲者的差异Q只需要实现这个接口就可以加蝲所有的资源Q他的默认实现是 DefaultResourceLoader?/p>

下面看一?Context ?Resource 是如何徏立关pȝQ首先看一下他们的cdpdQ?/p>
?9. Context ?Resource 的类关系?/font>
?9. Context ?Resource 的类关系? src=

从上囑֏以看出,Context 是把资源的加载、解析和描述工作委托l了 ResourcePatternResolver cL完成Q他相当于一个接头hQ他把资源的加蝲、解析和资源的定义整合在一起便于其他组件用。Core lg中还有很多类似的方式?/p>

Ioc 容器如何工作

前面介绍?Core lg、Bean lg?Context lg的结构与怺关系Q下面这里从使用者角度看一下他们是如何q行的,以及我们如何?Spring 完成各种功能QSpring 到底能有那些功能Q这些功能是如何得来的,下面介绍?/p>

如何创徏 BeanFactory 工厂

正如?2 描述的那PIoc 容器实际上就?Context lgl合其他两个lg共同构徏了一?Bean 关系|,如何构徏q个关系|?构徏的入口就?AbstractApplicationContext cȝ refresh Ҏ中。这个方法的代码如下Q?/p>
清单 1. AbstractApplicationContext.refresh
                        public void refresh() throws BeansException, IllegalStateException {
                        synchronized (this.startupShutdownMonitor) {
                        // Prepare this context for refreshing.
                        prepareRefresh();
                        // Tell the subclass to refresh the internal bean factory.
                        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
                        // Prepare the bean factory for use in this context.
                        prepareBeanFactory(beanFactory);
                        try {
                        // Allows post-processing of the bean factory in context subclasses.
                        postProcessBeanFactory(beanFactory);
                        // Invoke factory processors registered as beans in the context.
                        invokeBeanFactoryPostProcessors(beanFactory);
                        // Register bean processors that intercept bean creation.
                        registerBeanPostProcessors(beanFactory);
                        // Initialize message source for this context.
                        initMessageSource();
                        // Initialize event multicaster for this context.
                        initApplicationEventMulticaster();
                        // Initialize other special beans in specific context subclasses.
                        onRefresh();
                        // Check for listener beans and register them.
                        registerListeners();
                        // Instantiate all remaining (non-lazy-init) singletons.
                        finishBeanFactoryInitialization(beanFactory);
                        // Last step: publish corresponding event.
                        finishRefresh();
                        }
                        catch (BeansException ex) {
                        // Destroy already created singletons to avoid dangling resources.
                        destroyBeans();
                        // Reset 'active' flag.
                        cancelRefresh(ex);
                        // Propagate exception to caller.
                        throw ex;
                        }
                        }
                        }
                        

q个Ҏ是构徏整个 Ioc 容器q程的完整的代码Q了解了里面的每一行代码基本上׃解大部分 Spring 的原理和功能了?/p>

q段代码主要包含q样几个步骤Q?/p>

  • 构徏 BeanFactoryQ以便于产生所需?#8220;演员”
  • 注册可能感兴的事g
  • 创徏 Bean 实例对象
  • 触发被监听的事g

下面q合代码分析这几个q程?/p>

W二三句是在创建和配置 BeanFactory。这里是 refresh 也就是刷新配|,前面介绍?Context 有可更新的子c,q里正是实现q个功能Q当 BeanFactory 已存在是更斎ͼ如果没有新创徏。下面是更新 BeanFactory 的方法代码:


清单 2. AbstractRefreshableApplicationContext. refreshBeanFactory
                        protected final void refreshBeanFactory() throws BeansException {
                        if (hasBeanFactory()) {
                        destroyBeans();
                        closeBeanFactory();
                        }
                        try {
                        DefaultListableBeanFactory beanFactory = createBeanFactory();
                        beanFactory.setSerializationId(getId());
                        customizeBeanFactory(beanFactory);
                        loadBeanDefinitions(beanFactory);
                        synchronized (this.beanFactoryMonitor) {
                        this.beanFactory = beanFactory;
                        }
                        }
                        catch (IOException ex) {
                        throw new ApplicationContextException(
                        "I/O error parsing bean definition source for "
                        + getDisplayName(), ex);
                        }
                        }
                        

q个Ҏ实现?AbstractApplicationContext 的抽象方? refreshBeanFactoryQ这D代码清楚的说明?BeanFactory 的创E。注?BeanFactory 对象的类型的变化Q前面介l了他有很多子类Q在什么情况下使用不同的子c这非常关键。BeanFactory 的原始对象是 DefaultListableBeanFactoryQ这个非常关键,因ؓ他设计到后面对这个对象的多种操作Q下面看一下这个类的承层ơ类图:


?10. DefaultListableBeanFactory cȝ承关pd
?10. DefaultListableBeanFactory cȝ承关pd

Q查??10 的清晰版?/font>。)

从这个图中发现除?BeanFactory 相关的类外,q发C?Bean ?register 相关。这? refreshBeanFactory Ҏ中有一?loadBeanDefinitions(beanFactory) 找到答案,q个Ҏ开始加载、解?Bean 的定义,也就是把用户定义的数据结构{化ؓ Ioc 容器中的特定数据l构?/p>

q个q程可以用下面时序图解释Q?/p>
?11. 创徏 BeanFactory 时序?/font>
?11. 创徏 BeanFactory 时序? src=

Q查??11 的清晰版?/font>。)

Bean 的解析和登记程时序囑֦下:


?12. 解析和登?Bean 对象时序?/font>
?12. 解析和登?Bean 对象时序? src=

Q查??12 的清晰版?/font>。)

创徏?BeanFactory 后,接下L加一?Spring 本n需要的一些工LQ这个操作在 AbstractApplicationContext ?prepareBeanFactory Ҏ完成?/p>

AbstractApplicationContext 中接下来的三行代码对 Spring 的功能扩展性v了至关重要的作用。前两行主要是让你现在可以对已经构徏?BeanFactory 的配|做修改Q后面一行就是让你可以对以后再创? Bean 的实例对象时d一些自定义的操作。所以他们都是扩展了 Spring 的功能,所以我们要学习使用 Spring 必须对这一部分搞清楚?/p>

其中?invokeBeanFactoryPostProcessors Ҏ中主要是获取实现 BeanFactoryPostProcessor 接口的子cRƈ执行它的 postProcessBeanFactory ҎQ这个方法的声明如下Q?/p>
清单 3. BeanFactoryPostProcessor.postProcessBeanFactory
                        void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
                        throws BeansException;
                        

它的参数?beanFactoryQ说明可以对 beanFactory 做修改,q里注意q个 beanFactory ? ConfigurableListableBeanFactory cd的,q也印证了前面介l的不同 BeanFactory 所使用的场合不同,q里只能是可配置?BeanFactoryQ防止一些数据被用户随意修改?/p>

registerBeanPostProcessors Ҏ也是可以获取用户定义的实C BeanPostProcessor 接口的子c,q执行把它们注册?BeanFactory 对象中的 beanPostProcessors 变量中。BeanPostProcessor 中声明了两个ҎQpostProcessBeforeInitialization、postProcessAfterInitialization 分别用于?Bean 对象初始化时执行。可以执行用戯定义的操作?/p>

后面的几行代码是初始化监听事件和对系l的其他监听者的注册Q监听者必L ApplicationListener 的子cR?/p>

如何创徏 Bean 实例q构?Bean 的关pȝ

下面是 Bean 的实例化代码Q是?finishBeanFactoryInitialization Ҏ开始的?/p>
清单 4. AbstractApplicationContext.finishBeanFactoryInitialization
                        protected void finishBeanFactoryInitialization(
                        ConfigurableListableBeanFactory beanFactory) {
                        // Stop using the temporary ClassLoader for type matching.
                        beanFactory.setTempClassLoader(null);
                        // Allow for caching all bean definition metadata, not expecting further changes.
                        beanFactory.freezeConfiguration();
                        // Instantiate all remaining (non-lazy-init) singletons.
                        beanFactory.preInstantiateSingletons();
                        }
                        

从上面代码中可以发现 Bean 的实例化是在 BeanFactory 中发生的。preInstantiateSingletons Ҏ的代码如下:


清单 5. DefaultListableBeanFactory.preInstantiateSingletons
                        public void preInstantiateSingletons() throws BeansException {
                        if (this.logger.isInfoEnabled()) {
                        this.logger.info("Pre-instantiating singletons in " + this);
                        }
                        synchronized (this.beanDefinitionMap) {
                        for (String beanName : this.beanDefinitionNames) {
                        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                        if (!bd.isAbstract() && bd.isSingleton()
                        && !bd.isLazyInit()) {
                        if (isFactoryBean(beanName)) {
                        final FactoryBean factory =
                        (FactoryBean) getBean(FACTORY_BEAN_PREFIX+ beanName);
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null
                        && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged(
                        new PrivilegedAction<Boolean>() {
                        public Boolean run() {
                        return ((SmartFactoryBean) factory).isEagerInit();
                        }
                        }, getAccessControlContext());
                        }
                        else {
                        isEagerInit = factory instanceof SmartFactoryBean
                        && ((SmartFactoryBean) factory).isEagerInit();
                        }
                        if (isEagerInit) {
                        getBean(beanName);
                        }
                        }
                        else {
                        getBean(beanName);
                        }
                        }
                        }
                        }
                        }
                        

q里出现了一个非帔R要的 Bean —?FactoryBeanQ可以说 Spring 一大半的扩展的功能都与q个 Bean 有关Q这是个Ҏ?Bean 他是个工?BeanQ可以?Bean ?BeanQ这里的产生 Bean 是指 Bean 的实例,如果一个类l承 FactoryBean 用户可以自己定义产生实例对象的方法只要实C?getObject Ҏ。然而在 Spring 内部q个 Bean 的实例对象是 FactoryBeanQ通过调用q个对象?getObject Ҏp获取用户自定义生的对象Q从而ؓ Spring 提供了很好的扩展性。Spring 获取 FactoryBean 本n的对象是在前面加?& 来完成的?/p>

如何创徏 Bean 的实例对象以及如何构?Bean 实例对象之间的关联关pd Spring 中的一个核心关键,下面是这个过E的程图?/p>
?13.Bean 实例创徏程?/font>
?13.Bean 实例创徏程? src=

Q查??13 的清晰版?/font>。)

如果是普通的 Bean q接创Z的实例,是通过调用 getBean Ҏ。下面是创徏 Bean 实例的时序图Q?/p>
?14.Bean 实例创徏时序?/font>
?14.Bean 实例创徏时序? src=

Q查??14 的清晰版?/font>。)

q有一个非帔R要的部分是建立 Bean 对象实例之间的关p,q也?Spring 框架的核心竞争力Q何时、如何徏立他们之间的关系L下面的时序图Q?/p>
?15.Bean 对象关系建立
?15.Bean 对象关系建立

Q查??15 的清晰版?/font>。)

Ioc 容器的扩展点

现在q有一个问题就是如何让q些 Bean 对象有一定的扩展性,是可以加入用户的一些操作。那么有哪些扩展点呢Q?Spring 又是如何调用到这些扩展点的?

?Spring ?Ioc 容器来说Q主要有q么几个。BeanFactoryPostProcessorQ? BeanPostProcessor。他们分别是在构?BeanFactory 和构?Bean 对象时调用。还有就? InitializingBean ?DisposableBean 他们分别是在 Bean 实例创徏和销毁时被调用。用户可以实现这些接口中定义的方法,Spring ׃在适当的时候调用他们。还有一个是 FactoryBean 他是个特D的 BeanQ这?Bean 可以被用h多的控制?/p>

q些扩展炚w常也是我们使用 Spring 来完成我们特定Q务的地方Q如何精?Spring q你有没有掌握?Spring 有哪些扩展点Qƈ且如何用他们,要知道如何用他们就必须了解他们内在的机理。可以用下面一个比L解释?/p>

我们?Ioc 容器比作一个箱子,q个子里有若干个球的模子,可以用这些模子来造很多种不同的球Q还有一个造这些球模的机器Q这个机器可以生球模。那么他们的对应? pd?BeanFactory 是那个造球模的机器Q球模就?BeanQ而球模造出来的球就?Bean 的实例。那前面所说的几个扩展点又在什么地方呢Q?BeanFactoryPostProcessor 对应到当造球模被造出来时Q你有Z可以对其做出讑ֽ的修正,也就是他可以帮你修改球模。?InitializingBean ? DisposableBean 是在球模造球的开始和l束阶段Q你可以完成一些预备和扫尾工作。BeanPostProcessor 可以让你对球模造出来的球做出适当的修正。最后还有一? FactoryBeanQ它可是一个神奇的球模。这个球模不是预先就定型了,而是׃来给他确定它的ŞӞ既然你可以确定这个球模型的ŞӞ当然他造出? 的球肯定是你想要的球了Q这样在q个子里尼可以发现所有你惌的球

Ioc 容器如何为我所?/strong>

前面的介l了 Spring 容器的构E,?Spring 能ؓ我们做什么,Spring ?Ioc 容器又能做什么呢Q我们? Spring 必须要首先构?Ioc 容器Q没有它 Spring 无法工作QApplicatonContext.xml 是 Ioc 容器的默认配|文ӞSpring 的所有特性功能都是基于这?Ioc 容器工作的,比如后面要介l的 AOP?/p>

Ioc 它实际上是Z构徏了一个魔方,Spring Z搭好了骨骼架构,q个方到底能变Z么好的东西出来,q必要有你的参与。那我们怎么参与Q这是前面说的要了?Spring 中那有些扩展点,我们通过实现那些扩展Ҏ改变 Spring 的通用行ؓ。至于如何实现扩展点来得到我们想要的个性结果,Spring 中有很多例子Q其?AOP 的实现就?Spring 本n实现了其扩展Ҏ辑ֈ了它惌的特性功能,可以拿来参考?/p>


Spring ?AOP Ҏ详?/strong>

动态代理的实现原理

要了?Spring ?AOP 必d了解的动态代理的原理Q因?AOP 是Z动态代理实现的。动态代理还要从 JDK 本n说v?/p>

?Jdk ?java.lang.reflect 包下有个 Proxy c,它正是构造代理类的入口。这个类的结构入下:


?16. Proxy cȝ?/font>
?16. Proxy cȝ? src=

从上囑֏现最后面四个是公有方法。而最后一个方?newProxyInstance 是创徏代理对象的方法。这个方法的源码如下Q?/p>
清单 6. Proxy. newProxyInstance
                        public static Object newProxyInstance(ClassLoader loader,
                        Class<?>[] interfaces,
                        InvocationHandler h)
                        throws IllegalArgumentException {
                        if (h == null) {
                        throw new NullPointerException();
                        }
                        Class cl = getProxyClass(loader, interfaces);
                        try {
                        Constructor cons = cl.getConstructor(constructorParams);
                        return (Object) cons.newInstance(new Object[] { h });
                        } catch (NoSuchMethodException e) {
                        throw new InternalError(e.toString());
                        } catch (IllegalAccessException e) {
                        throw new InternalError(e.toString());
                        } catch (InstantiationException e) {
                        throw new InternalError(e.toString());
                        } catch (InvocationTargetException e) {
                        throw new InternalError(e.toString());
                        }
                        }
                        

q个Ҏ需要三个参敎ͼClassLoaderQ用于加载代理类?Loader c,通常q个 Loader 和被代理的类是同一? Loader cRInterfacesQ是要被代理的那些那些接口。InvocationHandlerQ就是用于执行除了被代理接口中方法之外的用户自定义的操作Q? 他也是用户需要代理的最l目的。用戯用目标方法都被代理到 InvocationHandler cM定义的唯一Ҏ invoke 中。这在后面再详解?/p>

下面q是看看 Proxy 如何产生代理cȝq程Q他构造出来的代理cd底是什么样子?下面揭晓啦?/p>
?17. 创徏代理对象时序?/font>
?17. 创徏代理对象时序? src=

其实从上图中可以发现正在构造代理类的是?ProxyGenerator ?generateProxyClass 的方法中。ProxyGenerator cd sun.misc 包下Q感兴趣的话可以看看他的源码?/p>

假如有这样一个接口,如下Q?/p>
清单 7. SimpleProxy c?/font>
                        public interface SimpleProxy {
                        public void simpleMethod1();
                        public void simpleMethod2();
                        }
                        

代理来生成的cȝ构如下:


清单 8. $Proxy2 c?/font>
                        public class $Proxy2 extends java.lang.reflect.Proxy implements SimpleProxy{
                        java.lang.reflect.Method m0;
                        java.lang.reflect.Method m1;
                        java.lang.reflect.Method m2;
                        java.lang.reflect.Method m3;
                        java.lang.reflect.Method m4;
                        int hashCode();
                        boolean equals(java.lang.Object);
                        java.lang.String toString();
                        void simpleMethod1();
                        void simpleMethod2();
                        }
                        

q个cM的方法里面将会是调用 InvocationHandler ?invoke ҎQ而每个方法也对应一个属性变量,q个属性变?m 也将传给 invoke Ҏ中的 Method 参数。整个代理就是这样实现的?/p>

Spring AOP 如何实现

从前面代理的原理我们知道Q代理的目的是调用目标方法时我们可以转而执?InvocationHandler cȝ invoke ҎQ所以如何在 InvocationHandler 上做文章是 Spring 实现 Aop 的关键所在?/p>

Spring ?Aop 实现是遵?Aop 联盟的约定。同?Spring 又扩展了它,增加了如 Pointcut、Advisor {一些接口得更加灵zR?/p>

下面?Jdk 动态代理的cdQ?/p>
?18. Jdk 动态代理的cd
?18. Jdk 动态代理的cd

上图清楚的显CZ Spring 引用?Aop Alliance 定义的接口。姑且不讨论 Spring 如何扩展 Aop AllianceQ先看看 Spring 如何实现代理cȝQ要实现代理cd Spring 的配|文件中通常是这样定一?Bean 的,如下Q?/p>
清单 9. 配置代理c?Bean
                        <bean id="testBeanSingleton"
                        class="org.springframework.aop.framework.ProxyFactoryBean">
                        <property name="proxyInterfaces">
                        <value>
                        org.springframework.aop.framework.PrototypeTargetTests$TestBean
                        </value>
                        </property>
                        <property name="target"><ref local="testBeanTarget"></ref> </property>
                        <property name="singleton"><value>true</value></property>
                        <property name="interceptorNames">
                        <list>
                        <value>testInterceptor</value>
                        <value>testInterceptor2</value>
                        </list>
                        </property>
                        </bean>
                        

配置上看到要讄被代理的接口Q和接口的实现类也就是目标类Q以及拦截器也就在执行目标方法之前被调用Q这?Spring 中定义的各种各样的拦截器Q可以选择使用?/p>

下面看看 Spring 如何完成了代理以及是如何调用拦截器的?/p>

前面提到 Spring Aop 也是实现其自w的扩展Ҏ完成q个Ҏ的Q从q个代理cd以看出它正是l承?FactoryBean ? ProxyFactoryBeanQFactoryBean 之所以特别就在它可以让你自定义对象的创徏Ҏ。当然代理对象要通过 Proxy cL动态生成?/p>

下面?Spring 创徏的代理对象的时序图:


?19.Spring 代理对象的?/font>
?19.Spring 代理对象的? src=

Spring 创徏了代理对象后Q当你调用目标对象上的方法时Q将都会被代理到 InvocationHandler cȝ invoke Ҏ中执行,q在前面已经解释。在q里 JdkDynamicAopProxy cdC InvocationHandler 接口?/p>

下面再看?Spring 是如何调用拦截器的,下面是这个过E的时序图:


?20.Spring 调用拦截?/font>
?20.Spring 调用拦截? src=

以上所说的都是 Jdk 动态代理,Spring q支持一U?CGLIB cM理,感兴自q吧?/p>


Spring 中设计模式分?/strong>

Spring 中用的设计模式也很多,比如工厂模式、单例模式、模版模式等Q在?Webx 框架的系l架构与设计模式》、?Tomcat 的系l架构与模式设计分析》已l有介绍Q这里就不赘qC。这里主要介l代理模式和{略模式?/p>

代理模式

代理模式原理

代理模式是l某一个对象创Z个代理对象,而由q个代理对象控制对原对象的引用,而创个代理对象就是可以在调用原对象是可以增加一些额外的操作。下面是代理模式的结构:


?21. 代理模式的结?/font>
?21. 代理模式的结? src=
  • SubjectQ抽象主题,它是代理对象的真实对象要实现的接口,当然q可以是多个接口l成?
  • ProxySubjectQ代理类除了实现抽象主题定义的接口外Q还必须持有所代理对象的引?
  • RealSubjectQ被代理的类Q是目标对象?

Spring 中如何实C理模?/strong>

Spring Aop ?Jdk 动态代理就是利用代理模式技术实现的。在 Spring 中除了实现被代理对象的接口外Q还会有 org.springframework.aop.SpringProxy ? org.springframework.aop.framework.Advised 两个接口。Spring 中用代理模式的l构囑֦下:


?22. Spring 中用代理模式的l构?/font>
?22. Spring 中用代理模式的l构? src=

$Proxy 是创徏的代理对象,?Subject 是抽象主题,代理对象是通过 InvocationHandler 来持有对目标对象的引用的?/p>

Spring 中一个真实的代理对象l构如下Q?/p>
清单 10 代理对象 $Proxy4
                        public class $Proxy4 extends java.lang.reflect.Proxy implements
                        org.springframework.aop.framework.PrototypeTargetTests$TestBean
                        org.springframework.aop.SpringProxy
                        org.springframework.aop.framework.Advised
                        {
                        java.lang.reflect.Method m16;
                        java.lang.reflect.Method m9;
                        java.lang.reflect.Method m25;
                        java.lang.reflect.Method m5;
                        java.lang.reflect.Method m2;
                        java.lang.reflect.Method m23;
                        java.lang.reflect.Method m18;
                        java.lang.reflect.Method m26;
                        java.lang.reflect.Method m6;
                        java.lang.reflect.Method m28;
                        java.lang.reflect.Method m14;
                        java.lang.reflect.Method m12;
                        java.lang.reflect.Method m27;
                        java.lang.reflect.Method m11;
                        java.lang.reflect.Method m22;
                        java.lang.reflect.Method m3;
                        java.lang.reflect.Method m8;
                        java.lang.reflect.Method m4;
                        java.lang.reflect.Method m19;
                        java.lang.reflect.Method m7;
                        java.lang.reflect.Method m15;
                        java.lang.reflect.Method m20;
                        java.lang.reflect.Method m10;
                        java.lang.reflect.Method m1;
                        java.lang.reflect.Method m17;
                        java.lang.reflect.Method m21;
                        java.lang.reflect.Method m0;
                        java.lang.reflect.Method m13;
                        java.lang.reflect.Method m24;
                        int hashCode();
                        int indexOf(org.springframework.aop.Advisor);
                        int indexOf(org.aopalliance.aop.Advice);
                        boolean equals(java.lang.Object);
                        java.lang.String toString();
                        void sayhello();
                        void doSomething();
                        void doSomething2();
                        java.lang.Class getProxiedInterfaces();
                        java.lang.Class getTargetClass();
                        boolean isProxyTargetClass();
                        org.springframework.aop.Advisor; getAdvisors();
                        void addAdvisor(int, org.springframework.aop.Advisor)
                        throws org.springframework.aop.framework.AopConfigException;
                        void addAdvisor(org.springframework.aop.Advisor)
                        throws org.springframework.aop.framework.AopConfigException;
                        void setTargetSource(org.springframework.aop.TargetSource);
                        org.springframework.aop.TargetSource getTargetSource();
                        void setPreFiltered(boolean);
                        boolean isPreFiltered();
                        boolean isInterfaceProxied(java.lang.Class);
                        boolean removeAdvisor(org.springframework.aop.Advisor);
                        void removeAdvisor(int)throws org.springframework.aop.framework.AopConfigException;
                        boolean replaceAdvisor(org.springframework.aop.Advisor,
                        org.springframework.aop.Advisor)
                        throws org.springframework.aop.framework.AopConfigException;
                        void addAdvice(org.aopalliance.aop.Advice)
                        throws org.springframework.aop.framework.AopConfigException;
                        void addAdvice(int, org.aopalliance.aop.Advice)
                        throws org.springframework.aop.framework.AopConfigException;
                        boolean removeAdvice(org.aopalliance.aop.Advice);
                        java.lang.String toProxyConfigString();
                        boolean isFrozen();
                        void setExposeProxy(boolean);
                        boolean isExposeProxy();
                        }
                        

{略模式

{略模式原理

{略模式֐思义是做某事的{略Q这在编E上通常是指完成某个操作可能有多U方法,q些Ҏ各有千秋Q可能有不同的适应的场合,然而这些操作方法都有可能用到。各一个操作方法都当作一个实现策略,使用者可能根据需要选择合适的{略?/p>

下面是策略模式的l构Q?/p>
?23. {略模式的结?/font>
?23. {略模式的结? src=

  • ContextQ用不同策略的环境Q它可以Ҏ自n的条仉择不同的策略实现类来完成所要的操作。它持有一个策略实例的引用。创建具体策略对象的Ҏ也可以由他完成?
  • StrategyQ抽象策略,定义每个{略都要实现的策略方?
  • ConcreteStrategyQ具体策略实现类Q实现抽象策略中定义的策略方?

Spring 中策略模式的实现

Spring 中策略模式用有多个地方Q如 Bean 定义对象的创Z及代理对象的创徏{。这里主要看一下代理对象创建的{略模式的实现?/p>

前面已经了解 Spring 的代理方式有两个 Jdk 动态代理和 CGLIB 代理。这两个代理方式的用正是用了{略模式。它的结构图如下所C:


?24. Spring 中策略模式结构图
?24. Spring 中策略模式结构图

在上面结构图中与标准的策略模式结构稍微有点不同,q里抽象{略?AopProxy 接口QCglib2AopProxy ? JdkDynamicAopProxy 分别代表两种{略的实现方式,ProxyFactoryBean 是代表 Context 角色Q它Ҏ条g选择使用 Jdk 代理方式q是 CGLIB 方式Q而另外三个类主要是来负责创徏具体{略对象QProxyFactoryBean 是通过依赖的方法来兌具体{略对象的,它是通过调用{略对象?getProxy(ClassLoader classLoader) Ҏ来完成操作?/p>


ȝ

本文通过?Spring 的几个核心组件入手,试图扑և构徏 Spring 框架的骨骼架构,q而分?Spring 在设计的一些设计理念,是否从中扑և一些好的设计思想Q对我们以后E序设计能提供一些思\。接着再详l分析了 Spring 中是如何实现q些理念的,以及在设计模式上是如何用的?/p>

通过分析 Spring l我一个很大的启示是其这套设计理念其实对我们有很强的借鉴意义Q它通过抽象复杂多变的对象,q一步做规范Q然后根据它定义的这套规范设计出一个容器,容器中构建它们的复杂关系Q其实现在有很多情况都可以用q种cM的处理方法?/p>

虽然我很x我对 Spring 的想法完全阐q清楚,但是所?#8220;书不言Q言不尽意?#8221;Q有什么不Ҏ者不清楚的地方大家还是看看其源码吧?/p>

 原文地址 http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/index.html

菜毛毛 2011-02-15 16:13 发表评论
]]>
java反射详解http://www.qpkxbc.shop/caizh2009/archive/2011/01/13/342941.html菜毛毛菜毛毛Thu, 13 Jan 2011 09:09:00 GMThttp://www.qpkxbc.shop/caizh2009/archive/2011/01/13/342941.htmlhttp://www.qpkxbc.shop/caizh2009/comments/342941.htmlhttp://www.qpkxbc.shop/caizh2009/archive/2011/01/13/342941.html#Feedback0http://www.qpkxbc.shop/caizh2009/comments/commentRss/342941.htmlhttp://www.qpkxbc.shop/caizh2009/services/trackbacks/342941.html阅读全文

菜毛毛 2011-01-13 17:09 发表评论
]]>
Java对象序列化(整理)http://www.qpkxbc.shop/caizh2009/archive/2011/01/13/342921.html菜毛毛菜毛毛Thu, 13 Jan 2011 05:29:00 GMThttp://www.qpkxbc.shop/caizh2009/archive/2011/01/13/342921.htmlhttp://www.qpkxbc.shop/caizh2009/comments/342921.htmlhttp://www.qpkxbc.shop/caizh2009/archive/2011/01/13/342921.html#Feedback0http://www.qpkxbc.shop/caizh2009/comments/commentRss/342921.htmlhttp://www.qpkxbc.shop/caizh2009/services/trackbacks/342921.html

 在网上看了很多有兛_列化的文 章,我自׃写了两篇Q现在感觉这些文章都没有很好的把序列化说清楚(包括我自己在?Q所以在此我ȝ前h以及自己的经验,用更显易懂的语a来描q? 该机Ӟ当然Q仍然会有不好的地方Q希望你看后可以指出Q作Z名程序员应该h不断探烦的精和强烈的求知欲望!

序列化概qͼ

      单来说序列化是一U用来处理对象流的机Ӟ所谓对象流也就是将对象的内容进行流化,的概念q里不用多说(是I/O)Q我们可以对化后的对象q行 d操作Q也可将化后的对象传输于网l之?注:要想对象传输于|络必须q行化)Q在对对象流q行d操作时会引发一些问题,而序列化机制正是用来 解决q些问题的!

问题的引出:

      如上所qͼd对象会有什么问题呢Q比如:我要对象写入一个磁盘文件而后再将其读出来会有什么问题吗Q别急,其中一个最大的问题是对象引用QD个例? 来说Q假如我有两个类Q分别是A和BQBcM含有一个指向Acd象的引用Q现在我们对两个c进行实例化{ A a = new A(); B b = new B(); }Q这时在内存中实际上分配了两个空_一个存储对象aQ一个存储对象bQ接下来我们惛_它们写入到磁盘的一个文件中去,在写入文g时出C问题Q因? 对象b包含对对象a的引用,所以系l会自动的将a的数据复制一份到b中,q样的话当我们从文g中恢复对象时(也就是重新加载到内存?Ӟ内存分配了三? I间Q而对象a同时在内存中存在两䆾Q想一惛_果吧Q如果我想修改对象a的数据的话,那不是还要搜索它的每一份拷贝来辑ֈ对象数据的一致性,q不是我们所 希望的!

以下序列化机制的解决ҎQ?/p>

1.保存到磁盘的所有对象都获得一个序列号(1, 2, 3{等)

2.当要保存一个对象时Q先查该对象是否被保存了?/p>

3.如果以前保存q,只需写入"与已l保存的h序列号x的对象相?的标讎ͼ否则Q保存该对象

通过以上的步骤序列化机制解决了对象引用的问题Q?/p>

序列化的实现Q?/p>

      需要被序列化的cd现Serializable接口Q该接口没有需要实现的ҎQimplements Serializable只是Z标注该对象是可被序列化的Q然后用一个输出流(如:FileOutputStream)来构造一? ObjectOutputStream(对象?对象Q接着Q用ObjectOutputStream对象的writeObject(Object obj)Ҏ可以将参数为obj的对象写?即保存其状?Q要恢复的话则用输入?/p>

例子Q?/p>

import java.io.*;

public class Test
{
    public static void main(String[] args)
    {
        Employee harry = new Employee("Harry Hacker", 50000);
        Manager manager1 = new Manager("Tony Tester", 80000);
        manager1.setSecretary(harry);
       
        Employee[] staff = new Employee[2];
       
        staff[0] = harry;
        staff[1] = manager1;
        try
        {
            ObjectOutputStream out = new ObjectOutputStream(
                new FileOutputStream("employee.dat"));
            out.writeObject(staff);
            out.close();
           
            ObjectInputStream in = new ObjectInputStream(
                new FileInputStream("employee.dat"));
            Employee[] newStaff = (Employee[])in.readObject();
            in.close();
  
            /**
             *通过harry对象来加?br />              *在secretary上反映出?br />              */
            newStaff[0].raiseSalary(10);
           
            for (int i = 0; i < newStaff.length; i++)
                System.out.println(newStaff[i]);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
   
}

class Employee implements Serializable
{
    public Employee(String n, double s)
    {
        name = n;
        salary = s;
    }
   
    /**
     *加薪?br />      */
    public void raiseSalary(double byPercent)
    {
        double raise = salary * byPercent / 100;
        salary += raise;
    }
   
    public String toString()
    {
        return getClass().getName()
            + "[name = "+ name
            + ",salary = "+ salary
            + "]";
    }
   
    private String name;
    private double salary;
}

class Manager extends Employee
{
    public Manager(String n, double s)
    {
        super(n, s);
        secretary = null;
    }
   
    /**
     *讄U书
     */
    public void setSecretary(Employee s)
    {
        secretary = s;
    }
   
    public String toString()
    {
        return super.toString()
            + "[secretary = "+ secretary
            + "]";
    }
   
    //secretary代表U书
    private Employee secretary; 
}

修改默认的序列化机制Q?nbsp;  

      ? 序列化的q程中,有些数据字段我们不想其序列化,对于此类字段我们只需要在定义时给它加上transient关键字即可,对于transient字段? 列化机制会蟩q不会将其写入文Ӟ当然也不可被恢复。但有时我们惛_某一字段序列化,但它在SDK中的定义却是不可序列化的cdQ这L话我们也必须把他 标注为transientQ可是不能写入又怎么恢复呢?好在序列化机制ؓ包含q种Ҏ问题的类提供了如下的Ҏ定义Q?/p>

private void readObject(ObjectInputStream in) throws

         IOException, ClassNotFoundException;

private void writeObject(ObjectOutputStream out) throws

         IOException;

(注:q些Ҏ定义时必LU有的,因ؓ不需要你昄调用Q序列化机制会自动调用的)

使用以上Ҏ我们可以手动寚w些你又想序列化又不可以被序列化的数据字段q行写出和读入操作?/p>

      下面是一个典型的例子Qjava.awt.geom包中的Point2D.Doublecd是不可序列化的,因ؓ该类没有实现Serializable接口Q在我的例子中将把它当作LabeledPointcM的一个数据字D,q演C如何将其序列化Q?/p>

import java.io.*;
import java.awt.geom.*;

public class TransientTest
{
    public static void main(String[] args)
    {
        LabeledPoint label = new LabeledPoint("Book", 5.00, 5.00);
        try
        {
            System.out.println(label);//写入?br />             ObjectOutputStream out = new ObjectOutputStream(new
                FileOutputStream("Label.txt"));
            out.writeObject(label);
            out.close();
           
            System.out.println(label);//写入?br />            
            ObjectInputStream in = new ObjectInputStream(new
                FileInputStream("Label.txt"));
            LabeledPoint label1 = (LabeledPoint)in.readObject();
            in.close();
            System.out.println(label1);//dq加1.0?br />         }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
   
}

class LabeledPoint implements Serializable
{
    public LabeledPoint(String str, double x, double y)
    {
        label = str;
        point = new Point2D.Double(x, y);
    }
   
    private void writeObject(ObjectOutputStream out) throws IOException
    {
        /**
         *必须通过调用defaultWriteObject()Ҏ来写?br />          *对象的描qC及那些可以被序列化的字段
         */
        out.defaultWriteObject();
        out.writeDouble(point.getX());
        out.writeDouble(point.getY());
    }
   
    private void readObject(ObjectInputStream in)
        throws IOException, ClassNotFoundException
    {
        /**
         *必须调用defaultReadObject()Ҏ
         */
        in.defaultReadObject();
        double x = in.readDouble() + 1.0;
        double y = in.readDouble() + 1.0;
        point = new Point2D.Double(x, y);
    }
   
    public String toString()
    {
        return getClass().getName()
            + "[label = "+ label
            + ", point.getX() = "+ point.getX()
            + ", point.getY() = "+ point.getY()
            + "]";
    }
   
    private  String label;
    transient private Point2D.Double point;
}
 

 




菜毛毛 2011-01-13 13:29 发表评论
]]>
Android获取Contact Number的例子(2.0pȝ以前的获取方式)http://www.qpkxbc.shop/caizh2009/archive/2010/12/17/341010.html菜毛毛菜毛毛Fri, 17 Dec 2010 09:45:00 GMThttp://www.qpkxbc.shop/caizh2009/archive/2010/12/17/341010.htmlhttp://www.qpkxbc.shop/caizh2009/comments/341010.htmlhttp://www.qpkxbc.shop/caizh2009/archive/2010/12/17/341010.html#Feedback0http://www.qpkxbc.shop/caizh2009/comments/commentRss/341010.htmlhttp://www.qpkxbc.shop/caizh2009/services/trackbacks/341010.html
  • String[] projection = new String[] {  
  • People._ID,  
  • People.NAME,  
  • People.NUMBER,  
  • };  
  •   
  • // Get the base URI for People table in Contacts content provider.  
  • // which is: content://contacts/people/  
  • Uri contactUri = People.CONTENT_URI;  
  •   
  • // Best way to retrieve a query; returns a managed query.  
  • Cursor peopleCursor = managedQuery (contactUri,  
  • projection, //Which columns to return.  
  • null, // WHERE clause--we won't specify.  
  • null, // Selection Args??  
  • People.DEFAULT_SORT_ORDER); // Order-by name  
  •   
  • // go to the beginning of the list  
  • peopleCursor.moveToFirst();  
  •   
  •   
  • // So, here we have a contact. We need to get the contact ID (_id) then  
  • // build the Uri to get the phones section of that user's record  
  • // which is a subdirectory of a contact record  
  •   
  • long personId = peopleCursor.getLong(peopleCursor.getColumnIndex("_id"));  
  •   
  • Uri personUri = ContentUris.withAppendedId(contactUri, personId );  
  •   
  • // So now the URL looks like: content://contacts/people/_id(where the actual id of the record is here)  
  • Uri phoneUri=  
  • Uri.withAppendedPath(personUri, Contacts.People.Phones.CONTENT_DIRECTORY);  
  •   
  • // Now the URL looks like: content://contacts/people/_id/phones (where phones is literally "phones")  
  •   
  • // Now get all the phone numbers for this contact  
  • Cursor phonesCursor = managedQuery(phoneUri,  
  • null,  
  • null,  
  • null,  
  • Phones.DEFAULT_SORT_ORDER);  
  •   
  • // We now have a cursor for all the phone numbers for that User ID  
  • // go to the beginning of the phone list.  
  • phonesCursor.moveToFirst();   


  • 菜毛毛 2010-12-17 17:45 发表评论
    ]]>
    android 2.2 获取联系人,电话Qƈ拨号http://www.qpkxbc.shop/caizh2009/archive/2010/12/17/341002.html菜毛毛菜毛毛Fri, 17 Dec 2010 08:58:00 GMThttp://www.qpkxbc.shop/caizh2009/archive/2010/12/17/341002.htmlhttp://www.qpkxbc.shop/caizh2009/comments/341002.htmlhttp://www.qpkxbc.shop/caizh2009/archive/2010/12/17/341002.html#Feedback0http://www.qpkxbc.shop/caizh2009/comments/commentRss/341002.htmlhttp://www.qpkxbc.shop/caizh2009/services/trackbacks/341002.html原创  android 2.2 获取联系人,电话Qƈ拨号 收藏

    该demo是第一ơ基于android开发?/p>

    主要功能有: d联系人姓名、号码,qlisetview 昄Q获取listview数据Qƈ发短信、或者拨?/p>

    package com.android.hello;

    import android.app.Activity;
    import android.content.Intent;   
    import android.database.Cursor;
    import android.graphics.Color;   
    import android.net.Uri;   
    import android.os.Bundle; 
    import android.telephony.PhoneNumberUtils; 
    import android.util.Log;   
    import android.view.View;   
    import android.widget.AdapterView;   
    import android.widget.LinearLayout;   
    import android.widget.ListAdapter;   
    import android.widget.ListView;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    import android.widget.Toast; 
    import android.provider.ContactsContract;

    import java.util.ArrayList;   
    import java.util.HashMap;
    import android.widget.SimpleAdapter;

    @SuppressWarnings("deprecation")
    public class hello extends Activity {
        /** Called when the activity is first created. */
       // @SuppressWarnings("deprecation")
    // @Override
     //  
     private static final String TAG="App";   
        ListView listView;   
        ListAdapter adapter;   
        /** Called when the activity is first created. */  
        @Override  
        public void onCreate(Bundle savedInstanceState) {   
            super.onCreate(savedInstanceState);   
           // setContentView(R.layout.main);   
            LinearLayout linearLayout=new LinearLayout(this);   
            linearLayout.setOrientation(LinearLayout.VERTICAL);   
            linearLayout.setBackgroundColor(Color.BLACK);   
            LinearLayout.LayoutParams param=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);   
               
            listView=new ListView(this);   
            listView.setBackgroundColor(Color.BLACK);   
               
            linearLayout.addView(listView,param);   
               
            this.setContentView(linearLayout);   
               
         
          //生成动态数l,加入数据
            ArrayList<HashMap<String, Object>> listItem = new ArrayList<HashMap<String, Object>>();        
            ArrayList<HashMap<String, Object>> listItemRead = new ArrayList<HashMap<String, Object>>();     
            Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null);      
            while (cursor.moveToNext())    
            {     
             HashMap<String, Object> map = new HashMap<String, Object>();
             String phoneName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
             map.put("ItemTitle", phoneName);//电话姓名
             String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));   
                String hasPhone = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));   
                
                if (hasPhone.compareTo("1") == 0)    
                {   
                    Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId,null, null);        
                    while (phones.moveToNext())    
                    {      
                     String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));       
                        String phoneTpye = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));       
                       
                        map.put("ItemText", phoneNumber); // 多个L如何处理
                        
                        Log.d(TAG,"testNum="+ phoneNumber + "type:"+phoneTpye); 
                    }        
                    phones.close();       
                }       
                Cursor emails = getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,null,ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + contactId,null, null);   
                while (emails.moveToNext())    
                {                    
                    String emailAddress = emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));   
                    String emailType = emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));      

                    Log.d(TAG,"testNum="+ emailAddress + "type:"+emailType); 
                }       
                emails.close();
                
                listItem.add(map); 
            }
            
            //生成适配器的Item和动态数l对应的元素   
            SimpleAdapter listItemAdapter = new SimpleAdapter(this,listItem,//数据?nbsp;   
                android.R.layout.simple_list_item_2,//ListItem的XML实现   
                //动态数l与ImageItem对应的子?nbsp;          
                new String[] {"ItemTitle", "ItemText"},    
                //ImageItem的XML文g里面的一个ImageView,两个TextView ID   
                new int[] {android.R.id.text1,android.R.id.text2}   
            );              
            
            listView.setAdapter(listItemAdapter);   
            cursor.close();  
            
            //listView.setEmptyView(findViewById(R.id.empty));   
               
            listView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){   
      
                public void onItemSelected(AdapterView<?> arg0, View arg1,   
                        int arg2, long arg3) {   
                    // TODO Auto-generated method stub   
                    //openToast("滚动刎ͼ"+arg0.getSelectedItemId());   
                    //短信发?nbsp;  
                 setTitle("选择"+arg2+"目");
                 openToast("选择"+arg0.getSelectedItemId()+"目");
        RelativeLayout lr = (RelativeLayout) arg1;
        TextView mText = (TextView) lr.getChildAt(1);
        openToast(mText.getText().toString());

        String number = mText.getText().toString();
        Log.d(TAG, "number=" + number);
        // 判断电话L的有效?br />     if (PhoneNumberUtils.isGlobalPhoneNumber(number)) {
         Intent intent = new Intent(Intent.ACTION_SENDTO, Uri
           .parse("smsto://" + number));
         intent.putExtra("sms_body", "The SMS text");
         startActivity(intent);             
        } 
                }   
      
                public void onNothingSelected(AdapterView<?> arg0) {   
                    // TODO Auto-generated method stub   
                       
                }   
                   
            });  
            
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){  

       public void onItemClick(AdapterView<?> arg0, View arg1,
         int position, long arg3) {
        // TODO Auto-generated method stub
        // openToast("Click"+Integer.toString(position+1)+"目");
        RelativeLayout lr = (RelativeLayout) arg1;
        TextView mText = (TextView) lr.getChildAt(1);
        openToast(mText.getText().toString());

        String number = mText.getText().toString();
        Log.d(TAG, "number=" + number);
        // 判断电话L的有效?br />     if (PhoneNumberUtils.isGlobalPhoneNumber(number)) {
         Intent intent = new Intent(Intent.ACTION_DIAL, Uri
           .parse("tel://" + number));
         startActivity(intent);
        }
       }
      });
     }
     
        private void openToast(String str){   
            Toast.makeText(this,str,Toast.LENGTH_SHORT).show();   
        }   



    菜毛毛 2010-12-17 16:58 发表评论
    ]]>
    java中文汉字排序http://www.qpkxbc.shop/caizh2009/archive/2010/12/17/340974.html菜毛毛菜毛毛Fri, 17 Dec 2010 05:22:00 GMThttp://www.qpkxbc.shop/caizh2009/archive/2010/12/17/340974.htmlhttp://www.qpkxbc.shop/caizh2009/comments/340974.htmlhttp://www.qpkxbc.shop/caizh2009/archive/2010/12/17/340974.html#Feedback2http://www.qpkxbc.shop/caizh2009/comments/commentRss/340974.htmlhttp://www.qpkxbc.shop/caizh2009/services/trackbacks/340974.html// Collator cL用来执行区分语言环境?String 比较的,q里选择使用CHINA         

    Comparator cmp = Collator.getInstance(java.util.Locale.CHINA); 

    TreeMap tree=new TreeMap(cmp);    

      String[] arr = {"张三", "李四", "王五"};       

    // 使根据指定比较器产生的顺序对指定对象数组q行排序?nbsp;     

       Arrays.sort(arr, cmp);      

      for (int i = 0; i < arr.length; i++)         

        System.out.println(arr[i]);

     

     

    <script>
     names = ["张三", "李四", "王五", "刘六"];
     names.sort(function(a,b){return a.localeCompare(b)});//a,b 为数la的某两个|自动传入
     alert(names);
    </script>

     

    ?

    CZ文本Q?/h4>



    String [] test = new String[] {
                    "作业",
                    "试",
                    "test",
                    "我们",
                    "。空",
                    "镂空",
                    "[",
                    "?,
                    "?
            };

    jdk 版本Q?/h4>

     1.5.6

    开发^収ͼ

     Eclipse 3.1

    关键字: 中文排序

     

    概述


    我们在应用程序中可能会经帔R到对中文排序的问题,例如姓名列表Q词汇表{等。对中文排序Q我们用比较多的是Ҏ汉语拼音发音来确定顺序?br />
    我们可能会经怋?nbsp;

    1. java.util.Set

     接口Q?

    1. java.util.Arrays .sort((T[] a, Comparator <? super  T> c))

     {类或方法对含有中文字符的对象进行排序,但是q些在默认情况下都是调用 

    1. String .CompareTo(String )

    ҎQ这个方法是比较2个字W的 codepoint valueQ如果第一个字W的值小于第二个Q则在排序结果中W一个会在前面,反之亦然?/p>

    1. java.text.Collator
    接口及其实现c?/h3>


    其实 java 中提供了和语a相关的类Q即 Collator 接口及其实现cR?

     是一个具体类Q它实现?nbsp;Comparator 接口中的 compare(Object, Object) Ҏ? RuleBasedCollator ҎҎ特定语言的默认规则比较字W,也可以按照指定的规则来比较,请参?nbsp;java API 获取此类的详l信 息?br /> 如果我们需要对一个有中文的数l进行排序,则可以用这个类。请看如下示例代码:

    1. import  java.util.*;
    2. import  java.text.*;
    3. public  class  Test
    4. {
    5.         String  [] test = new  String [] {
    6.                 "作业" ,
    7.                 "试" ,
    8.                 "test" ,
    9.                 "我们" ,
    10.                 "。空" ,
    11.                 "镂空" ,
    12.                 "[" ,
    13.                 "? ,
    14.                 "?
    15.         };
    16.       java.util.Arrays .sort(test, 
    17.               (RuleBasedCollator )Collator .getInstance(Locale .CHINA));
    18.       System .out.println("============" );
    19.       for (String  key : test)
    20.           System .out.println(key);
    21. }



    以上代码的输出结果ؓQ?br />
    ============
    [
    test
    。空

    我们
    作业
    ?br /> 镂空
    ?br />


    大家可能会发现只有一部分汉字是按照汉语拼x序了Q还有几个没有?/p>

    问题分析Q?/h3>


    GB2312:
    在简体中文中我们使用比较多的字符集是 GB2312-80Q简UCؓ GB2312Q这个字W集包含了目前最常用的汉字共?nbsp;6736 个。其中的汉字分ؓ两大c:

      常用汉字

     

      ơ常用汉?



    常用汉字按照汉语拼音来排序,而次常用汉字按照W画部首q行排序?br />
    体汉字在 Unicode 中一般是按照 gb2312 的码点值的序来放|的Q所以如果是常用汉字 java p够很准确的进行排序,但如果是ơ常用汉字,则就会出现问题。在以上CZ中,"?Q?? 属于ơ常用字?/p>

    解决ҎQ?/h3>


    RuleBasedCollator c?nbsp;getRules() Ҏ可以q回对应语言的规则设|。简体中文对应的规则?nbsp;gb2312 所对应的字W?/p>


      我们可以把其中的全部汉字提取出来

     

      对这些汉字重新排?/ol>

       

        利用RuleBasedCollator(String rules) 构造器新徏一个定制的 RuleBasedCollator

       

      参考代?/h3>


      在以下的代码中,我把排过序的汉字直接作ؓ String 对象攑֜c里面了Q如果要让代码变得简z一些,则可以把完整的规则(Ҏ字符Q排序汉字)存ؓ文g?/p>

      1. package  sorting;
      2. import  java.util.*;
      3. import  java.text.*;
      4. /**
      5.  * @author GaoJianMin
      6.  *
      7.  */
      8. public  class  ChineseGB2312Collator
      9. {
      10.     /**
      11.      * @return a customized RuleBasedCollator with Chinese characters (GB2312) sorted correctly
      12.      * 
      13.      */
      14.     public  static  final  RuleBasedCollator  getFixedGB2312Collator()
      15.     {
      16.         RuleBasedCollator  fixedGB2312Collator =null ;
      17.         try
      18.         {
      19.             fixedGB2312Collator = new  java.text.RuleBasedCollator (
      20.                     ChineseGB2312Collator.getGB2312SpecialChars() +
      21.                     GB2312Chars
      22.                     );
      23.         }catch (ParseException  e)
      24.         {
      25.             e.printStackTrace();
      26.         }
      27.         return  fixedGB2312Collator;
      28.     }
      29.     
      30.     /**
      31.      * @return the special characters in GB2312 charset.
      32.      * 
      33.      */
      34.     public  static  final  String  getGB2312SpecialChars()
      35.     {
      36.         RuleBasedCollator  zh_CNCollator = (RuleBasedCollator )Collator .getInstance(Locale .CHINA);
      37.         //index 2125 is the last symbol "?
      38.         return  zh_CNCollator.getRules().substring(0,2125);
      39.     }
      40.     
      41.     /**
      42.      * 6763 Chinese characters in GB2312 charset
      43.      */
      44.     public  static  final  String  GB2312Chars =
      45.         "<?lt;?lt;?lt; ?lt;?lt;?lt;哀<?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?  +
      46.         "<?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;W?lt;_?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;|?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;E?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;l?lt;?lt;?lt;?lt; ?lt;?lt;l?lt;?lt;膀<?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;W?lt;?lt;l?lt;?lt; ?lt;?lt;q?lt;?lt;y?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;U?lt; ?lt;W?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;畀<?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;{?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;髀< ?lt;?lt;?lt;?lt;W?lt;~?lt;?lt;?lt;?lt;?lt;?lt;?lt;H?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;~?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;y?lt;?lt;?lt;?lt;?lt;?lt;?lt; ~?lt;?lt;?lt;?lt;?lt;?lt;D?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;U?lt;?lt;?lt;?lt;<q?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;t?lt;?lt;C?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt;?lt; ?lt;?lt;?lt;?  ;
      1. }
      2. package  sorting;
      3. import  java.util.*;
      4. import  java.text.*;
      5. /**
      6.  * @author GaoJianMin
      7.  *
      8.  */
      9. public  class  ChineseGB2312Comparator implements  Comparator <String >, Comparable <String > {
      10.     private  RuleBasedCollator  GB2312Collator =
      11.         ChineseGB2312Collator.getFixedGB2312Collator();
      12.     private  String  str1;
      13.     
      14.     /**
      15.      * @param str1
      16.      */
      17.     public  ChineseGB2312Comparator(String  str1) {
      18.         this .str1 = str1;
      19.     }
      20.     /**
      21.      * 
      22.      */
      23.     public  ChineseGB2312Comparator() {
      24.         this .str1="" ;
      25.     }
      26.     /**
      27.      * @param str1
      28.      * @param str2
      29.      * @return an integer indicatint the comparison result
      30.      * @see java.util.Comparator#compare(Object, Object)
      31.      */
      32.     public  int  compare(String  str1, String  str2) {
      33.         return  GB2312Collator.compare(str1, str2);
      34.     }
      35.     /**
      36.      * @param str2
      37.      * @return an integer indicatint the comparison result
      38.      *  @see java.lang.Comparable#compareTo(Object)
      39.      */
      40.     public  int  compareTo(String  str2) {
      41.         return  GB2312Collator.compare(str1, str2);
      42.     }
      43. }


      试代码及结?/h3>
      代码Q?br />
      1. import  java.util.*;
      2. import  java.text.*;
      3. public  class  Test
      4. {
      5.         String  [] test = new  String [] {
      6.                 "作业" ,
      7.                 "试" ,
      8.                 "test" ,
      9.                 "我们" ,
      10.                 "。空" ,
      11.                 "镂空" ,
      12.                 "[" ,
      13.                 "? ,
      14.                 "?
      15.         };
      16.       java.util.Arrays .sort(test, new  ChineseGB2312Comparator());
      17.       System .out.println("============" );
      18.       for (String  key : test)
      19.           System .out.println(key);
      20. }


      ChineseGB2312Comparator cd时实C Comparator, Comparable 接口Q这样以后能够?nbsp;compare, compareTo Ҏ的时候都可以使用q个cR?/span>



      菜毛毛 2010-12-17 13:22 发表评论
      ]]> Struts1和Struts2的区别和Ҏ:http://www.qpkxbc.shop/caizh2009/archive/2010/12/14/340702.html菜毛毛菜毛毛Tue, 14 Dec 2010 13:55:00 GMThttp://www.qpkxbc.shop/caizh2009/archive/2010/12/14/340702.htmlhttp://www.qpkxbc.shop/caizh2009/comments/340702.htmlhttp://www.qpkxbc.shop/caizh2009/archive/2010/12/14/340702.html#Feedback0http://www.qpkxbc.shop/caizh2009/comments/commentRss/340702.htmlhttp://www.qpkxbc.shop/caizh2009/services/trackbacks/340702.htmlAction c? 
      • Struts1要求Actioncȝ承一个抽象基cRStruts1的一个普遍问题是使用抽象cȝE而不是接口?/span> 
      • Struts 2 Actioncd以实C个Action接口Q也可实现其他接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类?实现 常用的接口。Action接口不是必须的,M有execute标识的POJO对象都可以用作Struts2的Action对象?/span> 

      U程模式: 
      • Struts1 Action是单例模式ƈ且必LU程安全的,因ؓ仅有Action的一个实例来处理所有的h。单例策略限制了Struts1 Action能作的事Qƈ且要在开发时特别心。Action资源必须是线E安全的或同步的?/span> 
      • Struts2 Action对象为每一个请求生一个实例,因此没有U程安全问题。(实际上,servlet容器l每个请求生许多可丢弃的对象,q且不会D性能和垃圑֛攉题) 

      Servlet 依赖: 
      • Struts1 Action 依赖于Servlet API ,因ؓ当一个Action被调用时HttpServletRequest ?HttpServletResponse 被传递给executeҎ?/span> 
      • Struts 2 Action不依赖于容器Q允许Actionq容器单独被测试。如果需要,Struts2 Action仍然可以讉K初始的request和response。但是,其他的元素减或者消除了直接讉KHttpServetRequest ?HttpServletResponse的必要性?/span> 

      可测? 
      • 试Struts1 Action的一个主要问题是executeҎ暴露了servlet APIQ这使得试要依赖于容器Q。一个第三方扩展Q-Struts TestCaseQ-提供了一套Struts1的模拟对象(来进行测试)?/span> 
      • Struts 2 Action可以通过初始化、设|属性、调用方法来试Q?#8220;依赖注入”支持也ɋ试更容易?/span> 

      捕获输入: 
      • Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须l承一个基cR因为其他JavaBean不能用作ActionFormQ开发者经 常创建多余的cL莯入。动态BeanQDynaBeansQ可以作为创ZlActionForm的选择Q但是,开发者可能是在重新描q?创徏)已经?在的JavaBeanQ仍然会D有冗余的javabeanQ?/span> 
      • Struts 2直接使用Action属性作入属性,消除了对W二个输入对象的需求。输入属性可能是有自??属性的rich对象cd。Action属性能够通过 web面上的taglibs讉K。Struts2也支持ActionForm模式。rich对象cdQ包括业务对象,能够用作输入/输出对象。这U?ModelDriven Ҏ简化了taglib对POJO输入对象的引用?/span> 

      表达式语aQ?/span> 
      • Struts1 整合了JSTLQ因此用JSTL EL。这UEL有基本对象图遍历Q但是对集合和烦引属性的支持很弱?/span> 
      • Struts2可以使用JSTLQ但是也支持一个更强大和灵zȝ表达式语aQ-"Object Graph Notation Language" (OGNL). 

      l定值到面QviewQ? 
      • Struts 1使用标准JSP机制把对象绑定到面中来讉K?/span> 
      • Struts 2 使用 "ValueStack"技术,使taglib能够讉KD不需要把你的面QviewQ和对象l定h。ValueStack{略允许通过一pd名称相同但类型不同的属性重用页面(viewQ?/span> 

      cd转换Q?/span> 
      • Struts 1 ActionForm 属性通常都是Stringcd。Struts1使用Commons-Beanutilsq行cd转换。每个类一个{换器Q对每一个实例来说是不可配置的?/span> 
      • Struts2 使用OGNLq行cd转换。提供基本和常用对象的{换器?/span> 

      校验Q?/span> 
      • Struts 1支持在ActionForm的validateҎ中手动校验,或者通过Commons Validator的扩展来校验。同一个类可以有不同的校验内容Q但不能校验子对象?/span> 
      • Struts2支持通过validateҎ和XWork校验框架来进行校验。XWork校验框架使用为属性类cd定义的校验和内容校验Q来支持chain校验子属?/span> 

      Action执行的控Ӟ 
      • Struts1支持每一个模块有单独的Request ProcessorsQ生命周期)Q但是模块中的所有Action必须׃n相同的生命周期?/span> 
      • Struts2支持通过拦截器堆栈(Interceptor StacksQؓ每一个Action创徏不同的生命周期。堆栈能够根据需要和不同的Action一起用?/span>

      菜毛毛 2010-12-14 21:55 发表评论
      ]]>
      Android中添加Admobq告Q{http://www.qpkxbc.shop/caizh2009/archive/2010/12/10/340283.html菜毛毛菜毛毛Fri, 10 Dec 2010 09:42:00 GMThttp://www.qpkxbc.shop/caizh2009/archive/2010/12/10/340283.htmlhttp://www.qpkxbc.shop/caizh2009/comments/340283.htmlhttp://www.qpkxbc.shop/caizh2009/archive/2010/12/10/340283.html#Feedback2http://www.qpkxbc.shop/caizh2009/comments/commentRss/340283.htmlhttp://www.qpkxbc.shop/caizh2009/services/trackbacks/340283.html׃整整一天时_研究怎么通过?font style="background-color: #00ffff;">Android
      应用E序中添加Admobq告来赚钱。网上也有些教程Q不q说得不够详l,自己q得花时间摸索。ؓ了让后来者能更快开始Admobq告赚钱Q所以写个详l一点的教程Q供大家参考?/p>

      例子工程源码下蝲地址Q?使用览器自带的下蝲工具下蝲)http://cid-cb78b387364ae9a7.skydrive.live.com/browse.aspx/.Public/%e8%bd%af%e4%bb%b6/Andoroid
      当然Q我也参考了一些网上的资料Q主要有Q?/p>

      AdMobQ在android应用中嵌入广告的Ҏ
      如何?font style="background-color: #00ffff;">Android
      Market赚钱 part 2 - 免费app附带q告
      Publisher Starter Kit
      面向开发?Wiki ?AdMob

      好了Q现在让我从头开始说?#8230;…在这之前Q你不需要有M的帐P唯一需要的是有一个有效的email邮箱。只要按照下面的步骤一步步来,你就能通过Admob的广告插到自qE序中赚钱啦Q?/p>

      首先Q当然是需要注册一个Admob的帐受Admob的主|Q?a href="http://www.admob.com/">http://www.admob.com/ ?当然Q如果你对于览英文|页q有些障的话,可以d中文|站Q?a href="http://zhcn.admob.com/">http://zhcn.admob.com/ 。如果网站的文字q是英文Q你可以在网站主늚右下角的“Language”处,选择“中文Q简体)”。点击进入注册页面后Q有一些栏目需要填写,不要? q疑虑,像你注册一个论坛一P随便填下好了。最关键的是保证填写的email地址有效Q另外就是填上姓名,选择语言。帐L型我选择?#8220;不确?#8221;Q? 语言“中文Q简体)”?提交注册甌之后Q不久你׃收到用于认q激zdL电子邮gQ点Lz链接,可以了ȀzM的Admob帐号了~

      W二步就是设|你?font style="background-color: #00ffff;">Android? 用程序信息,q获得Admob的插入代码。登录你的Admob帐号后,在主늚左上方(Logo上面Q点?#8220;MarketplaceQ手机广告市场)”Q? q入面后,?#8220;Sites&AppsQ站点和应用E序Q?#8221;标签下,点击“Add Site/App”。选择我们熟悉的图标—? Android App ” 。这时会出现需要你填写一?#8220;详细信息”Q随便填上一些信息。(不要太过在意现在填写的东西,因ؓq些以后都是可以修改的)。比?#8220;Android Package URL” 我到现在都还没有填写Q描qCcȝQ想写就写点吧。填好详l信息后Q点?#8220;l箋”Q就可以到AdMob Android SDK 的下载页面了。下载这个SDKQ当Ӟq个很重要)?/p>

      The AdMob Android SDK includes:

      README: Get started with AdMob Android ads!
      AdMob Jar file: Required for publishing ads. Follow the documentation in javadoc/index.html and drop the AdMob Jar file into your project.
      Sample Projects: Examples of AdMob Android ads shown in the LunarLander application.

      W三步获取你的应用程序对应的Publisher ID。在下蝲面点击"Go to Sites/Apps"可以到你应用程序的理界面了。这时你会发现在q个面醒目的位|会有一个叫你填写详l信息的提示Q?/p>

      在我们发送Q何有待收入之前,您需要填写技术联p详l信息和付款首选项?/p>

      我们暂时可以不用它Q因为钱是会存在我们的Admob的̎户上的,{我们需要提现的时候,或者你惛_的时候再填就可以了。在下面的列表中Q选择? 的应用程序ƈq入。这个界面就是你的应用程序广告的理界面了,里面有比较多的功能,以后可以慢慢了解Q现在我们只需要知道两个东西,一个是发布? IDQPublisher IDQ,一个是你程序的状态。Publisher ID是一?5个字W的字符Ԍ而你E序的状态现在应该还是不zdQInactiveQ。我们下面要做的是怎么让它变ؓActive?/p>

      W四步代码编写——在你的应用E序中插入Admobq告。经q上面的步骤Q我们在|站上的讄告一个段落了Q现在我们终于要q入主题了,如何在自qAndroid应用E序中插入Admobq告。如果你不健忘的话,一定还记得我们之前下蝲的那个AdMob Android SDK 。解压它Q看看里面有些什么东ѝ这里面最重要的就是那个名?#8220;admob-sdk-android.jar”的包啦,Admob如何把q告加蝲?font style="background-color: #00ffff;">Android应用E序中的代码集成在这个包里,我们~写E序的时候就需要将q个包导入到我们的工E里面去。另外,解压出来的文件夹中还有一个名?#8220;javadoc”的文件夹Q打开它里面的index.html。它是关于Admob Android SDK的帮助文档,在Package 下的Setup下,有详l完整的在自q应用E序中插入广告的Ҏ介绍Q在q里我就hQ引用一下~


      Including the Jar
      Add the Jar file included with the SDK to your Android project as an external library. In your project's root directory create a subdirectory libs (this will already be done for you if you used Android's activitycreator). Copy the AdMob Jar file into that directory. For Eclipse projects:

      Go to the Properties of your project (right-click on your project from the Package Explorer tab and select Properties)
      Select "Java Build Path" from left panel
      Select "Libraries" tab from the main window
      Click on "Add JARs..."
      Select the JAR copied to the libs directory
      Click "OK" to add the SDK to your android project

      注意Q需要首先在你工E的根目录下新徏一个叫?#8220;libs”的文件夹Qƈ把之前所说的最重要的东?#8220;admob-sdk-android.jar”复制到里面?/p>


      AndroidManifest.xml

      Your AdMob publisher ID was given to you when creating your publisher account on www.admob.com before downloading this code. It is a 15-character code like a1496ced2842262. Just before the closing </application> tag add a line to set your publisher ID:


                      <!-- The application's publisher ID assigned by AdMob -->
                      <meta-data android:value="YOUR_ID_HERE" android:name="ADMOB_PUBLISHER_ID" />
              </application>
      Set any permissions not already included just before the closing </manifest> tag:
                      <!-- AdMob SDK permissions -->
                      <uses-permission android:name="android.permission.INTERNET" />
                      <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
              </manifest>

      Only the INTERNET permission is required. Setting ACCESS_COARSE_LOCATION (and/or ACCESS_FINE_LOCATION) allows narrowly geo-targeted ads be shown.

      q里需要注意的是,<meta-data android:value="YOUR_ID_HERE" android:name="ADMOB_PUBLISHER_ID" />中,我们只需要改的是"YOUR_ID_HERE"。这里需要你填上的ID是我们之前在Admob|站我们的应用程序管理页面上看到? Publisher IDQ而name="ADMOB_PUBLISHER_ID"是不应该改的。程序需要这个Key来查扑֯应的Value?/p>

      attrs.xml
      The attrs.xml file specifies custom AdView attributes in XML layout files. If your application does not already have an /res/values/attrs.xml file then create one and copy-and-paste the following into it. If you do have that file then just add the declare-styleable element:


              <?xml version="1.0" encoding="utf-8"?>
              <resources>
                      <declare-styleable name="com.admob.android.ads.AdView">
                              <attr name="testing" format="boolean" />
                              <attr name="backgroundColor" format="color" />
                              <attr name="textColor" format="color" />
                              <attr name="keywords" format="string" />
                              <attr name="refreshInterval" format="integer" />
                              <attr name="isGoneWithoutAd" format="boolean" />
                      </declare-styleable>
              </resources>

      q个Q没什么说的?/p>


      Placing an AdView in a Layout
      AdView widgets can be put into any XML layout now. The first step is to reference attrs.xml in your layout element by adding an xmlns line that includes your package name specified in AndroidManifest.xml:


              xmlns:yourapp=http://schemas.android.com/apk/res/yourpackage

      For example a simple screen with only an ad on it would look like:


              <?xml version="1.0" encoding="utf-8"?>
              <LinearLayout
                      xmlns:android="http://schemas.android.com/apk/res/android"
                      xmlns:admobsdk="http://schemas.android.com/apk/res/com.admob.android.example"
                      android:orientation="vertical"
                      android:layout_width="fill_parent"
                      android:layout_height="fill_parent">
         
                      <com.admob.android.ads.AdView
                              android:id="@+id/ad"
                              android:layout_width="fill_parent"
                              android:layout_height="wrap_content"
                              admobsdk:backgroundColor="#000000"
                              admobsdk:textColor="#FFFFFF"
                              admobsdk:keywords="Android application"
                      />
                             
              </LinearLayout>

      q里好像也没什么需要特别注意的Q注意加上xmlnsQ另外知道这里可以设|一个keywords

      Test Mode
      When you start integrating AdMob ads into your application it is recommended to use test mode. This always returns the same ad. Normal ad requests are not deterministic making it harder to be sure the ad view looks like you want (e.g. ad requests can timeout or may not fill).

      Once the ad shows up as you expect be sure to turn test mode off to get real ads. Never put your application into the Android Market with test mode enabled.

      Test mode can be enabled either by calling AdManager.setInTestMode(true) or by adding a "admobsdk:testing="true"" property to the ad in your XML layout (where "admobsdk" is the XML namespace for your application).


      讄Test Modeq个很关键,千万别将处于Test Mode的程序发布出MQ那样可赚不了钱啊~Q如果在AdView的属性中不加上admobsdk:testing="false"Q似乎程序也是不处于Test Mode的,不过最好还是加上吧?/p>

      W五步编译运行,q激zȝ序。编译运行你的程序,在模拟器上就可以看到效果啦~Q当然你的模拟器需要能上网Q关于怎么让模拟器上网呢?用\q应该 可以直接上,如果不是用\由,那么可能需要设|下Q具体方法大家自q上搜吧,具体忘了Q。如果你的应用程序能昄出广告,那么恭喜你,你的应用E序很快 ׃在Admob上被ȀzMQ需要一定的旉Q我的好像花了一个小时不刎ͼQ?/p>

      W六步在Admob|站上查看应用程序赚了多钱?#8220;手机q告市场”?gt;“报告”?gt;“站点和应用程序报?#8221;。选择你的应用E序Q然后点击页面最下面?#8220;创徏报告”?OKQ赚钱啦?/p>

      最后,我把我自己写的一个例子工E上传上来,大家可以下蝲来参考下。另外,我的工程广告作为移动的Qƈ且改变了它默认的宽度和背景,希望对如何在应用E序中摆攑ֹ告,起到一个抛砖引玉的作用。效果图如下Q哈哈,在模拟器跑的~)Q?/p>



      1.http://www.admob.com/注册一个帐P

      dAdd Mobile Site/appQ输入相关信息后Q提交完成,

      下蝲Androidq_使用的JARQ查看发布?ID?/p>

      2.然后JARdC的项目中

      Properties->Java Build Path->Libraries->Add JARs…->Select the JAR->OK

      3.~辑AndroidManifest.xml

      application节点中添?/p>

      <!– The application’s publisher ID assigned by AdMob –>

      <meta-data android:value=”a14ae1ce0357305″ android:name=”ADMOB_PUBLISHER_ID” />

      manifest节点d权限甌

      <!– AdMob SDK permissions –>

      <uses-permission android:name=”android.permission.INTERNET” />

      4.dattrs.xml

      /res/values/attrs.xml

      <?xml version=”1.0″ encoding=”utf-8″?>

      <resources>

      <declare-styleable name=”com.admob.android.ads.AdView”>

      <attr name=”testing” format=”boolean” />

      <attr name=”backgroundColor” format=”color” />

      <attr name=”textColor” format=”color” />

      <attr name=”keywords” format=”string” />

      <attr name=”refreshInterval” format=”integer” />

      <attr name=”isGoneWithoutAd” format=”boolean” />

      </declare-styleable>

      </resources>

      5.dq告lg

      <?xml version=”1.0″ encoding=”utf-8″?>

      <LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”

      xmlns:admobsdk=”http://schemas.android.com/apk/res/com.moandroid.livesports”

      android:orientation=”vertical”

      android:layout_width=”fill_parent”

      android:layout_height=”fill_parent”

      >

      <TextView

      android:layout_width=”fill_parent”

      android:layout_height=”wrap_content”

      android:text=”@string/hello”

      />

      <com.admob.android.ads.AdView

      android:id=”@+id/ad”

      android:layout_width=”fill_parent”

      android:layout_height=”wrap_content”

      admobsdk:backgroundColor=”#000000″

      admobsdk:textColor=”#FFFFFF”

      admobsdk:keywords=”Android application”

      admobsdk:refreshInterval=”60″

      />

      </LinearLayout>

      6.昄效果

      为免费app嵌入Admobq告Q进而获得广告收入?/p>

      adm



      菜毛毛 2010-12-10 17:42 发表评论
      ]]>区分Activity的四U加载模?/title><link>http://www.qpkxbc.shop/caizh2009/archive/2010/12/10/340227.html</link><dc:creator>菜毛毛</dc:creator><author>菜毛毛</author><pubDate>Fri, 10 Dec 2010 02:38:00 GMT</pubDate><guid>http://www.qpkxbc.shop/caizh2009/archive/2010/12/10/340227.html</guid><wfw:comment>http://www.qpkxbc.shop/caizh2009/comments/340227.html</wfw:comment><comments>http://www.qpkxbc.shop/caizh2009/archive/2010/12/10/340227.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.qpkxbc.shop/caizh2009/comments/commentRss/340227.html</wfw:commentRss><trackback:ping>http://www.qpkxbc.shop/caizh2009/services/trackbacks/340227.html</trackback:ping><description><![CDATA[http://marshal.easymorse.com/archives/2950 <div> <p>在多Activity开发中Q有可能是自己应用之间的Activity跌{Q或者夹带其他应用的可复用Activity。可能会希望跌{到原来某个Activity实例Q而不是生大量重复的Activity?/p> <p>q需要ؓActivity配置特定的加载模式,而不是用默认的加蝲模式?/p> <h4>加蝲模式分类及在哪里配置</h4> <p>Activity有四U加载模式:</p> <ul> <li>standard</li> <li>singleTop</li> <li>singleTask</li> <li>singleInstance</li> </ul> <p>讄的位|在AndroidManifest.xml文g中activity元素的android:launchMode属性:</p> <blockquote> <p><activity android:name="ActB" <strong>android:launchMode</strong>="singleTask"></activity></p> </blockquote> <p>也可以在Eclipse ADT中图形界面中~辑Q?/p> <p><a href="http://marshal.easymorse.com/wp-content/uploads/2010/07/image54.png"><img style="border: 0px none; display: inline;" title="image" alt="image" src="http://marshal.easymorse.com/wp-content/uploads/2010/07/image_thumb54.png" border="0" height="144" width="498" /></a> </p> <p> </p> <p>区分Activity的加载模式,通过CZ一目了然。这里编写了一个Activity AQActAQ和Activity BQActBQ@环蟩转的例子。对加蝲模式修改和代码做E微改动Q就可以说明四种模式的区别?/p> <h4>standard</h4> <p>首先说standard模式Q也是默认模式Q不需要配|launchMode。先只写一个名为ActA的ActivityQ?/p> <blockquote> <p>package com.easymorse.activities; </p> <p>import android.app.Activity; <br /> import android.content.Intent; <br /> import android.os.Bundle; <br /> import android.view.View; <br /> import android.view.View.OnClickListener; <br /> import android.widget.Button; <br /> import android.widget.LinearLayout; <br /> import android.widget.TextView; </p> <p>public class ActA extends Activity { <br />     /** Called when the activity is first created. */ <br />     @Override <br />     public void onCreate(Bundle savedInstanceState) { <br />         super.onCreate(savedInstanceState); <br />         TextView textView = new TextView(this); <br />         textView.setText(this + ""); <br />         Button button = new Button(this); <br />         button.setText("go actA"); <br />         button.setOnClickListener(new OnClickListener() { <br />             @Override <br />             public void onClick(View v) { <br />                 Intent intent = new Intent(); <br />                 intent.setClass(ActA.this, ActA.class); <br />                 startActivity(intent); <br />             } <br />         }); <br />         LinearLayout layout = new LinearLayout(this); <br />         layout.setOrientation(LinearLayout.VERTICAL); <br />         layout.addView(textView); <br />         layout.addView(button); <br />         this.setContentView(layout); <br />     } <br /> }</p> </blockquote> <p>例子中都没有用layoutQ免得看着|嗦。可见是ActA –> ActA的例子。在界面中打印出对象的toString值可以根据hash code识别是否创徏新ActA实例?/p> <p>W一个界面:</p> <p><a href="http://marshal.easymorse.com/wp-content/uploads/2010/07/image55.png"><img style="border: 0px none; display: inline;" title="image" alt="image" src="http://marshal.easymorse.com/wp-content/uploads/2010/07/image_thumb55.png" border="0" height="101" width="244" /></a> </p> <p>点击按钮后:</p> <p><a href="http://marshal.easymorse.com/wp-content/uploads/2010/07/image56.png"><img style="border: 0px none; display: inline;" title="image" alt="image" src="http://marshal.easymorse.com/wp-content/uploads/2010/07/image_thumb56.png" border="0" height="114" width="244" /></a> </p> <p>可以多点几次。发现每ơ都创徏了该Activity的新实例。standard的加载模式就是这LQintent发送给新的实例?/p> <p>现在点Android讑֤的回退键,可以看到是按照刚才创建Activity实例的倒序依次出现Q类似退栈的操作Q而刚才操作蟩转按钮的q程是压栈的操作。如下图Q?/p> <p><a href="http://marshal.easymorse.com/wp-content/uploads/2010/07/image57.png"><img style="border: 0px none; display: inline;" title="image" alt="image" src="http://marshal.easymorse.com/wp-content/uploads/2010/07/image_thumb57.png" border="0" height="233" width="244" /></a> </p> <h4>singleTop</h4> <p>singleTop和standard模式Q都会将intent发送新的实例(后两U模式不发送到新的实例Q如果已l有了的话)。不 q,singleTop要求如果创徏intent的时候栈已l有要创建的Activity的实例,则将intent发送给该实例,而不发送给新的实例?/p> <p>q是用刚才的CZQ只需launchMode改ؓsingleTopQ就能看到区别?/p> <p>q行的时候会发现Q按多少遍按钮,都是相同的ActiA实例Q因实例在栈Ӟ因此不会创徏新的实例。如果回退Q将退出应用?/p> <p><a href="http://marshal.easymorse.com/wp-content/uploads/2010/07/image58.png"><img style="border: 0px none; display: inline;" title="image" alt="image" src="http://marshal.easymorse.com/wp-content/uploads/2010/07/image_thumb58.png" border="0" height="144" width="244" /></a> </p> <p>singleTop模式Q可用来解决栈顶多个重复相同的Activity的问题?/p> <p>如果是A Activity跌{到B ActivityQ再跌{到A ActivityQ行为就和standard一样了Q会在B Activity跌{到A Activity的时候创建A Activity的新实例Q因为当时的栈顶不是A Activity实例?/p> <p>ActAcȝ作改动:</p> <blockquote> <p>package com.easymorse.activities; </p> <p>import android.app.Activity; <br /> import android.content.Intent; <br /> import android.os.Bundle; <br /> import android.view.View; <br /> import android.view.View.OnClickListener; <br /> import android.widget.Button; <br /> import android.widget.LinearLayout; <br /> import android.widget.TextView; </p> <p>public class ActA extends Activity { <br />     /** Called when the activity is first created. */ <br />     @Override <br />     public void onCreate(Bundle savedInstanceState) { <br />         super.onCreate(savedInstanceState); <br />         TextView textView = new TextView(this); <br />         textView.setText(this + ""); <br />         Button button = new Button(this); <br />         button.setText("go actB"); <br />         button.setOnClickListener(new OnClickListener() { <br />             @Override <br />             public void onClick(View v) { <br />                 Intent intent = new Intent(); <br />                 intent.setClass(ActA.this, ActB.class); <br />                 startActivity(intent); <br />             } <br />         }); <br />         LinearLayout layout = new LinearLayout(this); <br />         layout.setOrientation(LinearLayout.VERTICAL); <br />         layout.addView(textView); <br />         layout.addView(button); <br />         this.setContentView(layout); <br />     } <br /> }</p> <p> </p> </blockquote> <p>ActBc:</p> <blockquote> <p>package com.easymorse.activities; </p> <p>import android.app.Activity; <br /> import android.content.Intent; <br /> import android.os.Bundle; <br /> import android.view.View; <br /> import android.view.View.OnClickListener; <br /> import android.widget.Button; <br /> import android.widget.LinearLayout; </p> <p>public class ActB extends Activity { <br />     @Override <br />     protected void onCreate(Bundle savedInstanceState) { <br />         super.onCreate(savedInstanceState); <br />          Button button=new Button(this); <br />             button.setText("go actA"); <br />             button.setOnClickListener(new OnClickListener() { <br />                 @Override <br />                 public void onClick(View v) { <br />                     Intent intent=new Intent(); <br />                     intent.setClass(ActB.this, ActA.class); <br />                     startActivity(intent); <br />                 } <br />             }); <br />             LinearLayout layout=new LinearLayout(this); <br />             layout.addView(button); <br />             this.setContentView(layout); <br />     } <br /> }</p> <p> </p> </blockquote> <p>ActBcM用默认(standardQ加载,ActA使用singleTop加蝲。结果类g图:</p> <p><a href="http://marshal.easymorse.com/wp-content/uploads/2010/07/image59.png"><img style="border: 0px none; display: inline;" title="image" alt="image" src="http://marshal.easymorse.com/wp-content/uploads/2010/07/image_thumb59.png" border="0" height="211" width="244" /></a> </p> <p>如果把ActA的加载模式改为standardQ情况一栗?/p> <h4>singleTask</h4> <p>singleTask模式和后面的singleInstance模式都是只创Z个实例的?/p> <p>当intent到来Q需要创建singleTask模式Activity的时候,pȝ会检查栈里面是否已经有该Activity的实例。如果有直接intent发送给它?/p> <p>把上面singleTop的实例中的ActA的launchMode改ؓsingleTaskQActB的改为standard。那么会发现在ActA界面中按一ơ按钮:</p> <p><a href="http://marshal.easymorse.com/wp-content/uploads/2010/07/image60.png"><img style="border: 0px none; display: inline;" title="image" alt="image" src="http://marshal.easymorse.com/wp-content/uploads/2010/07/image_thumb60.png" border="0" height="217" width="244" /></a> </p> <p>然后在ActB1界面中按按钮Q因为ActA是singleTaskQ会使用原来的ActA1实例。这时候栈内的情况:</p> <p><a href="http://marshal.easymorse.com/wp-content/uploads/2010/07/image61.png"><img style="border: 0px none; display: inline;" title="image" alt="image" src="http://marshal.easymorse.com/wp-content/uploads/2010/07/image_thumb61.png" border="0" height="134" width="244" /></a></p> <p>如果多次按按钮蟩转,会发现始l只有ActA1q一个ActAcȝ实例?</p> <h4>singleInstance</h4> <p>解释singleInstance模式比较ȝ?/p> <p>首先要说一下TaskQQ务)的概c?/p> <p>如果是Swing或者WindowsE序Q可能有多个H口可以切换Q但是你无法在自q序中复用人家的窗口。注意是直接复用人家的二q制代码Q不是你拿到人家api后的源代码调用?/p> <p>Android可以做到Q让别h的程序直接复用你的ActivityQ类似桌面程序的H口Q?/p> <p>Android为提供这U机Ӟ引入了Task的概cTask可以认ؓ是一个栈Q可攑օ多个Activity。比如启动一个应用,那么 Android创Z一个TaskQ然后启动这个应用的入口ActivityQ就是intent-filter中配|ؓmain和launch的那? Q见<a href="http://marshal.easymorse.com/archives/2929" title="一个APK文g部v产生多个应用安装的效?>一个APK文g部v产生多个应用安装的效?/a>Q。这个Activity是根QRootQActivityQ可能会在它的界面调用其他ActivityQ这些Activity如果按照上面那三个模式,也会在这个栈QTaskQ中Q只是实例化的策略不同而已?/p> <p>验证的办法是调用和打印Activity的taskIdQ?/p> <blockquote> <p>TextView textView2 = new TextView(this); <br /> textView2.setText("task id: "+this.getTaskId());</p> </blockquote> <p>会发玎ͼ无论切换ActivityQtaskId是相同的?/p> <p>当然也可以在q个单一的Task栈中Q放入别人的ActivityQ比如google地图Q这LLq地图按回退键的时候,会退栈回到调用地囄Activity。对用户来说Qƈ不觉得在操作多个应用。这是Task的作用?/p> <p>但是Q有q样的需求,多个Task׃n一个ActivityQsingleTask是在一个task中共享一个ActivityQ?/p> <p>现成的例子是google地图。比如我有一个应用是导游斚w的,其中调用的google地图Activity。那么现在我比如按home键,然后到应用列表中打开google地图Q你会发现显C的是刚才的地图,实际上是同一个Activity?/p> <p>如果使用上面三种模式Q是无法实现q个需求的。google地图应用中有多个上下文ActivityQ比如\U查询等的,导游应用也有一些上下文Activity。在各自应用中回退要回退到各自的上下文Activity中?/p> <p>singleInstance模式解决了这个问题(l了q么半天才说到正题)。让q个模式下的Activity单独在一个task栈中。这个栈只有一个Activity。导游应用和google地图应用发送的intent都由q个Activity接收和展C?/p> <p>q里又有两个问题Q?/p> <ul> <li>如果是这U情况,多个task栈也可以看作一个应用。比如导游应用启动地图ActivityQ实际上是在导游应用task栈之? singleInstance模式创徏的(如果q没有的话,如果有就是直接显C它Q一个新栈,当这个栈里面的唯一ActivityQ地图Activity 回退的时候,只是把这个栈Ud了,q样q到导游应用刚才的Activity了;</li> <li>多个应用QTaskQ共享一个Activity要求q些应用都没有退出,比如刚才要用home键从导游应用切换到地囑ֺ用。因为,如果退出导游应用,而这时也地图应用q未q行的话Q那个单独的地图ActivityQtaskQ也会退Z?/li> </ul> <p>如果q是拿刚才的ActA和ActB的示例,可以把ActB的模式改为singleInstanceQActA为standardQ如果按一ơ按钮切换到ActBQ看到现象用C意囄DP</p> <p><a href="http://marshal.easymorse.com/wp-content/uploads/2010/07/image62.png"><img style="border: 0px none; display: inline;" title="image" alt="image" src="http://marshal.easymorse.com/wp-content/uploads/2010/07/image_thumb62.png" border="0" height="222" width="244" /></a> </p> <p>如果是第一ơ按钮切换到ActBQ在ActB在按按钮切换到ActAQ然后再回退Q示意图是:</p> <p><a href="http://marshal.easymorse.com/wp-content/uploads/2010/07/image63.png"><img style="border: 0px none; display: inline;" title="image" alt="image" src="http://marshal.easymorse.com/wp-content/uploads/2010/07/image_thumb63.png" border="0" height="166" width="342" /></a> </p> <p>另外Q可以看C个Activity的taskId是不同的?/p> </div> <img src ="http://www.qpkxbc.shop/caizh2009/aggbug/340227.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.qpkxbc.shop/caizh2009/" target="_blank">菜毛毛</a> 2010-12-10 10:38 <a href="http://www.qpkxbc.shop/caizh2009/archive/2010/12/10/340227.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <a href="http://www.qpkxbc.shop/"><span class="STYLE1">1һ152ͼ</span></a> <script>(function(){ var src = (document.location.protocol == "http:") ? "http://js.passport.qihucdn.com/11.0.1.js?9ed1f3a8f9c3ff069b7b95c01474c743":"https://jspassport.ssl.qhimg.com/11.0.1.js?9ed1f3a8f9c3ff069b7b95c01474c743"; document.write('<script src="' + src + '" id="sozz"><\/script>'); })(); </script> <a href="http://7064908.cn">˫ɫԤ׼ȷ</a> <a href="http://www.afnoqi.icu">pk10ڱ5 </a> <a href="http://0321582.cn">DzԤ׼ʮרţ</a> <a href="http://www.kiwhel.icu">ÿƻ</a> <a href="http://www.eircge.icu">ַֿ3ȫ߼ƻ</a> <a href="http://www.szslsa.icu">dһ϶ձ</a> <a href="http://5215087.com.cn">ʱʱʴС˫ھ</a> <a href="http://6305739.com.cn">˫ɫ6췽</a> <a href="http://www.wbsdpv.icu">ʽ6ж</a> <a href="http://www.vvdfhn.icu">տô׬</a> <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>