<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>xiaoshevip</title>
    <description></description>
    <link>http://xiaoshevip.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
          <item>
        <title>Webwork 2.2的Spring结合问题</title>
        <author>xiaoshevip</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xiaoshevip.javaeye.com">xiaoshevip</a>&nbsp;
                    链接：<a href="http://xiaoshevip.javaeye.com/blog/226544" style="color:red;">http://xiaoshevip.javaeye.com/blog/226544</a>&nbsp;
          发表时间: 2008年08月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          1、引子：<br />其实是ajoo的这篇“Nuts和Spring 1.2.6 效率对比”和“IoC容器的prototype性能测试 ”，他们在Javaeye上详细讨论了Spring的prototype的缺陷。<br />Spring的prototype指的就是singleton="false"的bean，具体可以看Spring参考手册“3.2.5. To singleton or not to singleton”介绍。 <br />2、Webwork 2.2的Spring结合问题：<br />Webwork 2.2已经抛弃自己的IoC，默认使用Spring的IoC。<br />上在OpenSymphony的官方Wiki，和jscud后来的几篇文章中没有特别提出prototype的问题。但是托他们的福，我们已经顺利的使Spring和Webwork良好的协同工作起来了。<br />可是而后的一些问题却把prototype的问题搞得神秘起来……<br />ajoo的测试中指出Spring的prototype性能很差，参见后面参考中的一篇文章和Javaeye的讨论。<br />而后又发现robbin在Javaeye的Wiki上面的“集成webwork和spring”中的最后注到：<br />“注意：目前并不推荐使用Spring来管理Webwork Action，因为对于prototype类型的bean来说，Spring创建bean和调用bean的效率是很低的！更进一步信息请看IoC容器的prototype性能测试”<br />这就使我们常用的Spring+Webwork2.2的连接中使用的prototype的问题被摆出来了。<br />我现在的项目中使用了prototype的方式将Webwork Action使用Spring进行显示的装配，我担心这个性能的问题会很严重，所以今天花了半天时间具体测试了一下。<br /><br />3、Prototype VS autowire的解释：<br />我不知道怎么命名两种方式好，所以这里先做个解释：<br />spring的配置中Action会有个id，如：<br /><br /><pre name="code" class="java">&lt;bean id="someAction" class="com.tin.action.SomeAction" parent="basicActionWithAuthtication" singleton="false">
 &lt;property name="someDAO">
  &lt;ref bean="someDAO" />
 &lt;/property>
&lt;/bean></pre>我指的prototype方式就是在xwork中这样配置：<br /><br />&lt;action name="someAction" class="someAction"><br />而autowire方式就是指在xwork中这样配置：<br /><br />&lt;action name="someAction" class="com.tin.action.SomeAction"><br />看起来相同，但其实不同（我以前发过帖子，其中说这几种方法都可，但是其实它们的机制是不同的。<br /><br />4、Portotye和autowire在XWork的SpringObjectFactory中是如何运作的：<br /><br />我们先看一下代码，就能明白两者的区别了：<br /><br /><pre name="code" class="java">public Object buildBean(String beanName, Map extraContext) throws Exception {
try {
            return appContext.getBean(beanName);
        } catch (NoSuchBeanDefinitionException e) {
            Class beanClazz = getClassInstance(beanName);
            return buildBean(beanClazz, extraContext);
        }
    }

    public Object buildBean(Class clazz, Map extraContext) throws Exception {
        Object bean;

        try {
            bean = autoWiringFactory.autowire(clazz, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false);
        } catch (UnsatisfiedDependencyException e) {
            // Fall back
            bean = super.buildBean(clazz, extraContext);
        }

        bean = autoWiringFactory.applyBeanPostProcessorsBeforeInitialization(bean, bean.getClass().getName());
        // We don't need to call the init-method since one won't be registered.
        bean = autoWiringFactory.applyBeanPostProcessorsAfterInitialization(bean, bean.getClass().getName());

        return autoWireBean(bean, autoWiringFactory);
    }

    public Object autoWireBean(Object bean) {
        return autoWireBean(bean, autoWiringFactory);
    }</pre><br /><br />如果按照autowire配置会使用第二个buildBean方法，而prototype会使用第一个buildBean方法。<br /><br />5、我的测试，首先测试SpringObjectFactory的理论效率：<br /><br /><pre name="code" class="java">public class testSpringObjectFactory extends TestCase {
    protected FileSystemXmlApplicationContext appContext;
    protected SpringObjectFactory sof = null;
    protected Map map = null;
    final String[] paths = {
            "WebRoot/WEB-INF/applicationContext.xml",
            "WebRoot/WEB-INF/spring-daos.xml",
            "WebRoot/WEB-INF/spring-actions.xml"
        };

    protected void setUp() throws Exception {
        super.setUp();
        appContext = new FileSystemXmlApplicationContext(paths);

        sof = new SpringObjectFactory();
        sof.setApplicationContext(appContext);
        sof.setAutowireStrategy(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);

        map = new HashMap();
    }

    public void testSpringObjectFacotyWithAutowire() {
        long begin = System.currentTimeMillis();

        try {
            for (int i = 0; i &lt; 100000; i++) {
                sof.buildBean("com.wqh.action.XinfangNewsAction", map);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        long end = System.currentTimeMillis();
        System.out.println("**************************Used time:" +
            (begin - end));
    }

    public void testSpringObjectFacotyWithPrototype() {
        long begin = System.currentTimeMillis();

        try {
            for (int i = 0; i &lt; 100000; i++) {
                sof.buildBean("xinfangNewsAction", map);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        long end = System.currentTimeMillis();
        System.out.println("**************************Used time:" +
            (begin - end));
    }
    
    public void testSpringObjectFacotyWithSpringProxyableObjectFactory() {
        sof = new SpringProxyableObjectFactory();
        sof.setApplicationContext(appContext);
        sof.setAutowireStrategy(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);

        long begin = System.currentTimeMillis();

        try {
            for (int i = 0; i &lt; 100000; i++) {
                sof.buildBean("com.wqh.action.XinfangNewsAction", map);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        long end = System.currentTimeMillis();
        System.out.println("**************************Used time:" +
            (begin - end));
    }
} </pre><br />重要的是测试结果：<br />**************************Used time:-16875<br />**************************Used time:-80500<br />**************************Used time:-12703（使用SpringProxyableObjectFactory()这个实现）<br />prototype是autowire运行时间的4.77X倍，十分可观。<br /><br />5.5 巨大的反差，原来是我搞错了配置，发现了幕后黑手：<br />第二天，我又重新运行了5里面的测试。但是结果令人吃惊，运行了十多次，结果于昨天反差巨大，prototype方式获得的bean反而性能最快！<br />摘要两次测量结果<br />**************************Autowire Used time:-17578<br />**************************Prototype Used time:-7609<br />**************************Proxy Used time:-13063<br />-----------------------------------------------<br />**************************Autowire Used time:-17047<br />**************************Prototype Used time:-7609<br />**************************Proxy Used time:-12797<br />这是为什么呢？我百思不得其解，问题出在哪里呢？后来经过跟踪svn里面的提交纪录。我发现，我在昨天测试以后，把spring配置文件中的&lt;beans default-autowire="autodetect">变成了&lt;beans>。也就是没有打开自动检测的autowire！<br />而后就真相大白了。我有配置上default-autowire="autodetect"进行测试，结果：<br />**************************Autowire Used time:-16937<br />**************************Prototype Used time:-79750<br />**************************Proxy Used time:-12578<br />这和昨天的测试结果完全相同。也就是说我昨天写的4.77x的结果其实没有实际意义。倒是说明了Spring和Webwork集成的文章上面说的default-autowire="autodetect"是很坏的实践，即失去了name的灵活性也带来了巨大的性能损失。<br />而如果使用默认的Spring autowire配置下，prototype的性能已经很好了，实际上它工作起来应该是最快的。<br /><br />6、在实际的Web项目中的性能对比：<br />我使用了我的一个小项目，就是反复调用一个action获取一个页面，其中有一个DAO注入。使用了JMeter进行了一个测试：2个线程，间隔0.5秒，循环50次，对比“据和报告中的”Throughput，单位/sec。<br />使用autowire方式：Avg. 148.34（吞吐量越高越好）<br />使用prototype方式：Avg. 138.5<br />也就是说在实际应用中两者也是有性能差距的，后者大约是前者性能的93%。<br />具体代码我不放出了，因为意义不大，大家也可以自己动手试验一下。<br />补充说明：<br />首先注意这个测试是在default-autowire="autodetect"下进行的。<br />测试的这个Action其实是一个空Action，它没有调用service和DAO，只是直接return SUCCESS，然后dispatcher到一个静态内容的jsp页面。我的本意是为了能够在获取Action占据的时间比例比较高的情况下分析性能区别。但是实际上却间接的夸大了在真正的实际应用中的性能差距。实际应用中如果加上service、DAO等逻辑的执行时间、模板View的渲染时间还有广域网上的网络传输时间，那么获取Action实例的时间差距可能就微乎其微了。<br /><br /><br />7、后续：<br />经过今天的思考，可以说完全改变了想法，重新汇总一下：<br />a、在不使用default-autowire="autodetect"时，Webwork 2.2的xwork中的action class使用spring的bean id配置的理论性能最好。而且，我认为如果不是为了追求配置上的简单，严重推荐关闭spring的default-autowire。<br />b、在使用default-autowire="autodetect、name、class"时，需要考虑你的需求。如果不使用Spring AOP提供的功能则在Webwork 2.2的xwork中的action class使用class全名比较好。如果使用Spring AOP的功能，则还是使用bean id。<br />c、在Spring中是否使用default-autowire是个需要慎重考虑的问题。autowire如果打开，命名会受到限制（class则更不推荐，受限更大，参考相关文档），它所带来的配置简化我认为只算是小小的语法糖果，背后却是吃掉它所埋下的隐患。<br />d、6中的测试还是有些说明意义的。7%的性能差距是在使用了default-autowire的方式下得出的，其中测试的那个action其实没有执行什么逻辑，而是一个直接dispatcher到success view的action，如果有商业逻辑包装，则性能差据估计会更小。因为实际上Action的执行过程、service、DAO等逻辑的执行过程和模板View的渲染过程（网络延迟）才是耗时大户。所以，关于性能应该下的结论是，prototype与否，在实际应用中性能差距是很小的，基本可以忽略不计。我们讨论的更多是编码的更好的实践。<br />e、autowire不使用Spring AOP相对还是trade off，因为虽然配置简单一点，但是对于使用Spring的声明性事务等内容会带来麻烦。虽然XML不那么好，但是显示配置带来的好处还是很多的。<br />f、谢谢robbin的提示。关于事务我也是无奈，放弃Action事务后难道给DAO多封装一层事务？如何没有事务依然使用HibernateDAOSurpport？Acegi的确不适合Web，使用WW的Inteceptor可以实现更舒适的解决方案。<br />g、SpringProxyableObjectFactory的问题……使用上难道只能改代码？找了半天没有这个东西的介绍。看来还是需要看看代码。不过发现现在Webwork和Xwork的代码又变动了很多……<br />h、我的测试是在Webwork2.2+Spring 1.2.6环境下测试的
          <br/><br/>
          <span style="color:red;">
            <a href="http://xiaoshevip.javaeye.com/blog/226544#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/138' target='_blank'><span style="color:red;font-weight:bold;">加入阿里巴巴，发展潜力无限</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 11 Aug 2008 11:49:23 +0800</pubDate>
        <link>http://xiaoshevip.javaeye.com/blog/226544</link>
        <guid>http://xiaoshevip.javaeye.com/blog/226544</guid>
      </item>
          <item>
        <title>从Spring和Hibernate的设计来理解合理的异常处理体系</title>
        <author>xiaoshevip</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xiaoshevip.javaeye.com">xiaoshevip</a>&nbsp;
                    链接：<a href="http://xiaoshevip.javaeye.com/blog/224685" style="color:red;">http://xiaoshevip.javaeye.com/blog/224685</a>&nbsp;
          发表时间: 2008年08月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          关于在应用程序中如何设计合理的异常体系，在《深入浅出Hibernate》这本书中有一大段详细的论述，另外一些JAVA界的高人也先后发表过专门的文章来讨论这个问题，书中也给出的文章的链接。<br /><br />其实，通过Hibernate和Spring中对异常处理的态度，就可以看出一些好的设计原则。在Hibernate2的时候，调用Hibernate的API时必须处理一个CheckedException，这和使用JDBC时是一样的，Hibernate的作者在后来的一封Email中也承认多少是受了JDBC的影响。但是面对这种底层的异常，我们能做些什么呢？继续抛上去或者捕获后什么都不做。这样的做法只能使程序中充满了重复的没有太大意义的try...catch...代码，而其功能和一个UncheckedException没用太大差别。所以Spring包装了Hibernate后抛出了一个UnckeckedException。后来Hibernate也意识到抛出一个UncheckedException是一种更合适的做法，所以在Hibernate3中不再抛出CheckedException了。<br /><br />今天又看到了一个Spring的特性，更加说明了Spring在异常处理方面的思路和态度：<br /><br />默认的情况下，spring只有当unchecked exception被抛出时，才rollback事务。 <br /><pre name="code" class="java">
&lt;property name="transactionAttributes"> 
    &lt;props> 
            &lt;prop key="insert*">PROPAGATION_REQUIRED,- MyCheckedException,+MyUnCheckedException&lt;/prop> 
            &lt;prop key="update*">PROPAGATION_REQUIRED&lt;/prop> 
            &lt;prop key="*">PROPAGATION_REQUIRED,readOnly&lt;/prop> 
        &lt;/props> 
&lt;/property> 

</pre>-MyCheckedException 指定如果方法抛出MyCheckedException或它的子类，事务将 会自动回滚。 <br />＋MyUnCheckedException 指定如果方法抛出MyUnCheckedException或它的子类，事务仍将会提交。<br /><br />可我们的项目中是怎么做的呢？<br /><br />几乎在每一层的每一个方法中都try...catch一下，然后在catch代码块中抛出一个OAException，这个OAException是New出来的而且还是一个CheckedException，包含了一句简单的异常信息，如“数据访问出现错误……”。这样做的后果有两个，一是又回到了Hibernate2的那种异常处理方式，使代码变的复杂了，有时候只有一两行的代码就可以搞定的现在要写个十多行的异常处理代码。二是丢掉了原始的异常信息，这一点就更严重了，由于OAException是New出来的，所以只包含了简单的提示信息，而真正出现异常的原始信息却丢掉了。另外，从上面Spring事务的回滚机制来看，如果采用默认配置，事务都会变的形同虚设了。<br /><br />这种异常处理体系对程序员是一种痛苦，对程序设计来说是一种缺憾！
          <br/><br/>
          <span style="color:red;">
            <a href="http://xiaoshevip.javaeye.com/blog/224685#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/138' target='_blank'><span style="color:red;font-weight:bold;">加入阿里巴巴，发展潜力无限</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 05 Aug 2008 17:18:21 +0800</pubDate>
        <link>http://xiaoshevip.javaeye.com/blog/224685</link>
        <guid>http://xiaoshevip.javaeye.com/blog/224685</guid>
      </item>
          <item>
        <title>Log4j的使用</title>
        <author>xiaoshevip</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xiaoshevip.javaeye.com">xiaoshevip</a>&nbsp;
                    链接：<a href="http://xiaoshevip.javaeye.com/blog/214487" style="color:red;">http://xiaoshevip.javaeye.com/blog/214487</a>&nbsp;
          发表时间: 2008年07月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在强调可重用组件开发的今天，除了自己从头到尾开发一个可重用的日志操作类外，Apache为我们提供了一个强有力的日志操作包-Log4j。 <br /><br />Log4j是Apache的一个开放源代码项目，通过使用Log4j，我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、<br />UNIX Syslog守护进程等；我们也可以控制每一条日志的输出格式；通过定义每一条日志信息的级别，我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是，<br />这些可以通过一个配置文件来灵活地进行配置，而不需要修改应用的代码。 <br /><br />此外，通过Log4j其他语言接口，您可以在C、C++、.Net、PL/SQL程序中使用Log4j，其语法和用法与在Java程序中一样，使得多语言分布式系统得到一个统一一致的<br />日志组件模块。而且，通过使用各种第三方扩展，您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中。<br /><br />说明：下面分为三部分，第一部分讲解如何配置log4j，第二部分为对log4j.properties配置文件中的各个属性的讲解，第三部分为对log4j的详细讲解，如果只想配<br />置上log4j，那么只需要看前两个部分就可以，如果想对log4j深入了解，则还需看第三部分。<br /><br />一、Log4j配置<br /><br />第一步：加入log4j-1.2.8.jar到lib下。<br /><br />第二步：在CLASSPATH下建立log4j.properties。内容如下：<br /><br /><pre name="code" class="java">log4j.rootCategory=INFO, stdout , R

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n

log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=D:\\Tomcat 5.5\\logs\\qc.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n
log4j.logger.com.neusoft=DEBUG
log4j.logger.com.opensymphony.oscache=ERROR
log4j.logger.net.sf.navigator=ERRORlog4j.logger.org.apache.commons=ERROR
log4j.logger.org.apache.struts=WARN
log4j.logger.org.displaytag=ERROR
log4j.logger.org.springframework=DEBUG
log4j.logger.com.ibatis.db=WARN
log4j.logger.org.apache.velocity=FATAL

log4j.logger.com.canoo.webtest=WARN

log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN
log4j.logger.org.hibernate=DEBUG
log4j.logger.org.logicalcobwebs=WARN</pre><br />第三步：相应的修改其中属性，修改之前就必须知道这些都是干什么的，在第二部分讲解。<br /><br />第四步：在要输出日志的类中加入相关语句：<br /><br />定义属性：protected final Log log = LogFactory.getLog(getClass());<br /><br />在相应的方法中：<br /><pre name="code" class="java">if (log.isDebugEnabled()){
       log.debug(“System …..”);
}</pre><br /><br />二、Log4j说明<br /><br />1 log4j.rootCategory=INFO, stdout , R<br /><br />此句为将等级为INFO的日志信息输出到stdout和R这两个目的地，stdout和R的定义在下面的代码，可以任意起名。<br />等级可分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL，如果配置OFF则不打出任何信息，如果配置为INFO这样只显示INFO, WARN, ERROR的log信息，<br />而DEBUG信息不会被显示，具体讲解可参照第三部分定义配置文件中的logger。<br /><br />3 log4j.appender.stdout=org.apache.log4j.ConsoleAppender<br /><br />此句为定义名为stdout的输出端是哪种类型，可以是<br /><br />org.apache.log4j.ConsoleAppender（控制台）， <br /><br />org.apache.log4j.FileAppender（文件）， <br /><br />org.apache.log4j.DailyRollingFileAppender（每天产生一个日志文件），<br /><br />org.apache.log4j.RollingFileAppender（文件大小到达指定尺寸的时候产生一个新的文件）<br /><br />org.apache.log4j.WriterAppender（将日志信息以流格式发送到任意指定的地方）<br /><br />具体讲解可参照第三部分定义配置文件中的Appender。<br /><br />4 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout<br /><br />此句为定义名为stdout的输出端的layout是哪种类型，可以是<br /><br />org.apache.log4j.HTMLLayout（以HTML表格形式布局）， <br /><br />org.apache.log4j.PatternLayout（可以灵活地指定布局模式）， <br /><br />org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串）， <br /><br />org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息）<br /><br />具体讲解可参照第三部分定义配置文件中的Layout。<br /><br />5 log4j.appender.stdout.layout.ConversionPattern= [QC] %p [%t] %C.%M(%L) | %m%n<br /><br />如果使用pattern布局就要指定的打印信息的具体格式ConversionPattern，打印参数如下：<br /><br />%m 输出代码中指定的消息<br /><br />%p 输出优先级，即DEBUG，INFO，WARN，ERROR，FATAL <br /><br />%r 输出自应用启动到输出该log信息耗费的毫秒数 <br /><br />%c 输出所属的类目，通常就是所在类的全名 <br /><br />%t 输出产生该日志事件的线程名 <br /><br />%n 输出一个回车换行符，Windows平台为“rn”，Unix平台为“n” <br /><br />%d 输出日志时间点的日期或时间，默认格式为ISO8601，也可以在其后指定格式，比如：%d{yyyy MMM dd HH:mm:ss,SSS}，输出类似：2002年10月18日 22：10：28，921 <br /><br />%l 输出日志事件的发生位置，包括类目名、发生的线程，以及在代码中的行数。<br /><br />[QC]是log信息的开头，可以为任意字符，一般为项目简称。<br /><br />输出的信息<br /><br />[TS] DEBUG [main] AbstractBeanFactory.getBean(189) | Returning cached instance of singleton bean 'MyAutoProxy'<br /><br />具体讲解可参照第三部分定义配置文件中的格式化日志信息。<br /><br />7 log4j.appender.R=org.apache.log4j.DailyRollingFileAppender<br /><br />此句与第3行一样。定义名为R的输出端的类型为每天产生一个日志文件。<br /><br />8 log4j.appender.R.File=D:\\Tomcat 5.5\\logs\\qc.log<br /><br />此句为定义名为R的输出端的文件名为D:\\Tomcat 5.5\\logs\\qc.log<br /><br />可以自行修改。<br /><br />9 log4j.appender.R.layout=org.apache.log4j.PatternLayout<br /><br />与第4行相同。<br /><br />10 log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n<br /><br />与第5行相同。<br /><br />12 log4j.logger.com. neusoft =DEBUG<br /><br />指定com.neusoft包下的所有类的等级为DEBUG。<br /><br />可以把com.neusoft改为自己项目所用的包名。<br /><br />13 log4j.logger.com.opensymphony.oscache=ERROR<br /><br />14 log4j.logger.net.sf.navigator=ERROR<br /><br />这两句是把这两个包下出现的错误的等级设为ERROR，如果项目中没有配置EHCache，则不需要这两句。<br /><br />15 log4j.logger.org.apache.commons=ERROR<br /><br />16 log4j.logger.org.apache.struts=WARN<br /><br />这两句是struts的包。<br /><br />17 log4j.logger.org.displaytag=ERROR<br /><br />这句是displaytag的包。（QC问题列表页面所用）<br /><br />18 log4j.logger.org.springframework=DEBUG<br /><br />此句为Spring的包。<br /><br />24 log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN<br /><br />25 log4j.logger.org.hibernate=DEBUG<br /><br />此两句是hibernate的包。<br /><br />以上这些包的设置可根据项目的实际情况而自行定制。<br /><br />三、log4j详解<br /><br />1、定义配置文件<br /><br />Log4j支持两种配置文件格式，一种是XML格式的文件，一种是Java特性文件log4j.properties（键=值）。下面将介绍使用log4j.properties文件作为配置文件的方法:<br /><br />①、配置根Logger<br /><br />Logger 负责处理日志记录的大部分操作。 <br /><br />其语法为：<br /><br />log4j.rootLogger = [ level ] , appenderName, appenderName, …<br /><br />其中，level 是日志记录的优先级，分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的级别。Log4j建议只使用四个级别，优先级从高到低分别是<br />ERROR、WARN、INFO、DEBUG。通过在这里定义的级别，您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别，只有等于及高于这个<br />级别的才进行处理，则应用程序中所有DEBUG级别的日志信息将不被打印出来。ALL:打印所有的日志，OFF：关闭所有的日志输出。 appenderName就是指定日志信息<br />输出到哪个地方。可同时指定多个输出目的地。<br /><br />②、配置日志信息输出目的地 Appender<br /><br />Appender 负责控制日志记录操作的输出。 <br /><br />其语法为：<br /><br />log4j.appender.appenderName = fully.qualified.name.of.appender.class <br /><br />log4j.appender.appenderName.option1 = value1 <br /><br />… <br /><br />log4j.appender.appenderName.optionN = valueN <br /><br />这里的appenderName为在①里定义的，可任意起名。<br /><br />其中，Log4j提供的appender有以下几种： <br /><br />org.apache.log4j.ConsoleAppender（控制台）， <br /><br />org.apache.log4j.FileAppender（文件）， <br /><br />org.apache.log4j.DailyRollingFileAppender（每天产生一个日志文件），<br /><br />org.apache.log4j.RollingFileAppender（文件大小到达指定尺寸的时候产生一个新的文件），可通过log4j.appender.R.MaxFileSize=100KB设置文件大小，<br />还可通过log4j.appender.R.MaxBackupIndex=1设置为保存一个备份文件。 <br /><br />org.apache.log4j.WriterAppender（将日志信息以流格式发送到任意指定的地方）<br /><br />例如：log4j.appender.stdout=org.apache.log4j.ConsoleAppender<br /><br />定义一个名为stdout的输出目的地，ConsoleAppender为控制台。<br /><br />③、配置日志信息的格式（布局）Layout<br /><br />Layout 负责格式化Appender的输出。<br /><br />其语法为：<br /><br />log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class <br /><br />log4j.appender.appenderName.layout.option1 = value1 <br /><br />… <br /><br />log4j.appender.appenderName.layout.optionN = valueN <br /><br />其中，Log4j提供的layout有以下几种： <br /><br />org.apache.log4j.HTMLLayout（以HTML表格形式布局）， <br /><br />org.apache.log4j.PatternLayout（可以灵活地指定布局模式）， <br /><br />org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串）， <br /><br />org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息）<br /><br />2、格式化日志信息<br /><br />Log4J采用类似C语言中的printf函数的打印格式格式化日志信息，打印参数如下： <br /><br />%m 输出代码中指定的消息<br /><br />%p 输出优先级，即DEBUG，INFO，WARN，ERROR，FATAL <br /><br />%r 输出自应用启动到输出该log信息耗费的毫秒数 <br /><br />%c 输出所属的类目，通常就是所在类的全名 <br /><br />%t 输出产生该日志事件的线程名 <br /><br />%n 输出一个回车换行符，Windows平台为“rn”，Unix平台为“n” <br /><br />%d 输出日志时间点的日期或时间，默认格式为ISO8601，也可以在其后指定格式，比如：%d{yyyy MMM dd HH:mm:ss,SSS}，输出类似：2002年10月18日 22：10：28，921 <br /><br />%l 输出日志事件的发生位置，包括类目名、发生的线程，以及在代码中的行数。<br /><br />3、在代码中使用Log4j<br /><br />我们在需要输出日志信息的类中做如下的三个工作：<br /><br />1、导入所有需的commongs-logging类：<br /><br />import org.apache.commons.logging.Log;<br /><br />import org.apache.commons.logging.LogFactory;<br /><br />2、在自己的类中定义一个org.apache.commons.logging.Log类的私有静态类成员：<br /><br />private final Log log = LogFactory.getLog(getClass());<br /><br />LogFactory.getLog()方法的参数使用的是当前类的class。<br /><br />3、使用org.apache.commons.logging.Log类的成员方法输出日志信息：<br /><pre name="code" class="java">if (log.isDebugEnabled()){
    log.debug("111");
}

if (log.isInfoEnabled()){
    log.info("222");
}

if (log.isWarnEnabled()){
    log.warn("333");
}

if (log.isErrorEnabled()){
    log.error("444");
}

if (log.isFatalEnabled()){
    log.fatal("555")
}  
</pre>
          <br/><br/>
          <span style="color:red;">
            <a href="http://xiaoshevip.javaeye.com/blog/214487#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/138' target='_blank'><span style="color:red;font-weight:bold;">加入阿里巴巴，发展潜力无限</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 14 Jul 2008 10:29:59 +0800</pubDate>
        <link>http://xiaoshevip.javaeye.com/blog/214487</link>
        <guid>http://xiaoshevip.javaeye.com/blog/214487</guid>
      </item>
          <item>
        <title>Hibernate的缓存</title>
        <author>xiaoshevip</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xiaoshevip.javaeye.com">xiaoshevip</a>&nbsp;
                    链接：<a href="http://xiaoshevip.javaeye.com/blog/186611" style="color:red;">http://xiaoshevip.javaeye.com/blog/186611</a>&nbsp;
          发表时间: 2008年04月25日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          缓存是介于应用程序和物理数据源之间，其作用是为了降低应用程序对物理数据源访问的频次，从而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复制，应用程序在运行时从缓存读写数据，在特定的时刻或事件会同步缓存和物理数据源的数据。<br /><br />　　缓存的介质一般是内存，所以读写速度很快。但如果缓存中存放的数据量非常大时，也会用硬盘作为缓存介质。缓存的实现不仅仅要考虑存储的介质，还要考虑到管理缓存的并发访问和缓存数据的生命周期。<br /><br />　　Hibernate的缓存包括Session的缓存和SessionFactory的缓存，其中SessionFactory的缓存又可以分为两类：内置缓存和外置缓存。Session的缓存是内置的，不能被卸载，也被称为Hibernate的第一级缓存。SessionFactory的内置缓存和Session的缓存在实现方式上比较相似，前者是SessionFactory对象的一些集合属性包含的数据，后者是指Session的一些集合属性包含的数据。SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句，映射元数据是映射文件中数据的拷贝，而预定义SQL语句是在Hibernate初始化阶段根据映射元数据推导出来，SessionFactory的内置缓存是只读的，应用程序不能修改缓存中的映射元数据和预定义SQL语句，因此SessionFactory不需要进行内置缓存与映射文件的同步。SessionFactory的外置缓存是一个可配置的插件。在默认情况下，SessionFactory不会启用这个插件。外置缓存的数据是数据库数据的拷贝，外置缓存的介质可以是内存或者硬盘。SessionFactory的外置缓存也被称为Hibernate的第二级缓存。<br /><br />　　Hibernate的这两级缓存都位于持久化层，存放的都是数据库数据的拷贝，那么它们之间的区别是什么呢？为了理解二者的区别，需要深入理解持久化层的缓存的两个特性：缓存的范围和缓存的并发访问策略。<br /><br />　　持久化层的缓存的范围<br /><br />　　缓存的范围决定了缓存的生命周期以及可以被谁访问。缓存的范围分为三类。<br /><br />　　1 事务范围：缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期，当事务结束时，缓存也就结束生命周期。在此范围下，缓存的介质是内存。事务可以是数据库事务或者应用事务，每个事务都有独自的缓存，缓存内的数据通常采用相互关联的的对象形式。<br /><br />　　2 进程范围：缓存被进程内的所有事务共享。这些事务有可能是并发访问缓存，因此必须对缓存采取必要的事务隔离机制。缓存的生命周期依赖于进程的生命周期，进程结束时，缓存也就结束了生命周期。进程范围的缓存可能会存放大量的数据，所以存放的介质可以是内存或硬盘。缓存内的数据既可以是相互关联的对象形式也可以是对象的松散数据形式。松散的对象数据形式有点类似于对象的序列化数据，但是对象分解为松散的算法比对象序列化的算法要求更快。<br /><br />　　3 集群范围：在集群环境中，缓存被一个机器或者多个机器的进程共享。缓存中的数据被复制到集群环境中的每个进程节点，进程间通过远程通信来保证缓存中的数据的一致性，缓存中的数据通常采用对象的松散数据形式。<br /><br />　　对大多数应用来说，应该慎重地考虑是否需要使用集群范围的缓存，因为访问的速度不一定会比直接访问数据库数据的速度快多少。<br /><br />　　持久化层可以提供多种范围的缓存。如果在事务范围的缓存中没有查到相应的数据，还可以到进程范围或集群范围的缓存内查询，如果还是没有查到，那么只有到数据库中查询。事务范围的缓存是持久化层的第一级缓存，通常它是必需的；进程范围或集群范围的缓存是持久化层的第二级缓存，通常是可选的。<br /><br />　　持久化层的缓存的并发访问策略<br /><br />　　当多个并发的事务同时访问持久化层的缓存的相同数据时，会引起并发问题，必须采用必要的事务隔离措施。<br /><br />　　在进程范围或集群范围的缓存，即第二级缓存，会出现并发问题。因此可以设定以下四种类型的并发访问策略，每一种策略对应一种事务隔离级别。<br /><br />　　事务型：仅仅在受管理环境中适用。它提供了Repeatable Read事务隔离级别。对于经常被读但很少修改的数据，可以采用这种隔离类型，因为它可以防止脏读和不可重复读这类的并发问题。<br /><br />　　读写型：提供了Read Committed事务隔离级别。仅仅在非集群的环境中适用。对于经常被读但很少修改的数据，可以采用这种隔离类型，因为它可以防止脏读这类的并发问题。<br /><br />　　非严格读写型：不保证缓存与数据库中数据的一致性。如果存在两个事务同时访问缓存中相同数据的可能，必须为该数据配置一个很短的数据过期时间，从而尽量避免脏读。对于极少被修改，并且允许偶尔脏读的数据，可以采用这种并发访问策略。　　只读型：对于从来不会修改的数据，如参考数据，可以使用这种并发访问策略。<br /><br />　　事务型并发访问策略是事务隔离级别最高，只读型的隔离级别最低。事务隔离级别越高，并发性能就越低。<br /><br />　　什么样的数据适合存放到第二级缓存中？<br /><br />　　1、很少被修改的数据<br /><br />　　2、不是很重要的数据，允许出现偶尔并发的数据<br /><br />　　3、不会被并发访问的数据<br /><br />　　4、参考数据<br /><br />　　不适合存放到第二级缓存的数据？<br /><br />　　1、经常被修改的数据<br /><br />　　2、财务数据，绝对不允许出现并发<br /><br />　　3、与其他应用共享的数据。<br /><br />　　Hibernate的二级缓存<br /><br />　　如前所述，Hibernate提供了两级缓存，第一级是Session的缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务，因此它的缓存是事务范围的缓存。第一级缓存是必需的，不允许而且事实上也无法比卸除。在第一级缓存中，持久化类的每个实例都具有唯一的OID。<br /><br />　　第二级缓存是一个可插拔的的缓存插件，它是由SessionFactory负责管理。由于SessionFactory对象的生命周期和应用程序的整个过程对应，因此第二级缓存是进程范围或者集群范围的缓存。这个缓存中存放的对象的松散数据。第二级对象有可能出现并发问题，因此需要采用适当的并发访问策略，该策略为被缓存的数据提供了事务隔离级别。缓存适配器用于把具体的缓存实现软件与Hibernate集成。第二级缓存是可选的，可以在每个类或每个集合的粒度上配置第二级缓存。<br /><br />　　Hibernate的二级缓存策略的一般过程如下：<br /><br />　　1) 条件查询的时候，总是发出一条select * from table_name where …. （选择所有字段）这样的SQL语句查询数据库，一次获得所有的数据对象。<br /><br />　　2) 把获得的所有数据对象根据ID放入到第二级缓存中。<br /><br />　　3) 当Hibernate根据ID访问数据对象的时候，首先从Session一级缓存中查；查不到，如果配置了二级缓存，那么从二级缓存中查；查不到，再查询数据库，把结果按照ID放入到缓存。<br /><br />　　4) 删除、更新、增加数据的时候，同时更新缓存。<br /><br />　　Hibernate的二级缓存策略，是针对于ID查询的缓存策略，对于条件查询则毫无作用。为此，Hibernate提供了针对条件查询的Query缓存。<br /><br />　　Hibernate的Query缓存策略的过程如下：<br /><br />　　1) Hibernate首先根据这些信息组成一个Query Key，Query Key包括条件查询的请求一般信息：SQL, SQL需要的参数，记录范围（起始位置rowStart，最大记录个数maxRows)，等。<br /><br />　　2) Hibernate根据这个Query Key到Query缓存中查找对应的结果列表。如果存在，那么返回这个结果列表；如果不存在，查询数据库，获取结果列表，把整个结果列表根据Query Key放入到Query缓存中。<br /><br />　　3) Query Key中的SQL涉及到一些表名，如果这些表的任何数据发生修改、删除、增加等操作，这些相关的Query Key都要从缓存中清空。
          <br/><br/>
          <span style="color:red;">
            <a href="http://xiaoshevip.javaeye.com/blog/186611#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/138' target='_blank'><span style="color:red;font-weight:bold;">加入阿里巴巴，发展潜力无限</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 25 Apr 2008 09:28:18 +0800</pubDate>
        <link>http://xiaoshevip.javaeye.com/blog/186611</link>
        <guid>http://xiaoshevip.javaeye.com/blog/186611</guid>
      </item>
          <item>
        <title>Btree</title>
        <author>xiaoshevip</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xiaoshevip.javaeye.com">xiaoshevip</a>&nbsp;
                    链接：<a href="http://xiaoshevip.javaeye.com/blog/172867" style="color:red;">http://xiaoshevip.javaeye.com/blog/172867</a>&nbsp;
          发表时间: 2008年03月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          整理中……http://dreamhead.blogbus.com/
          <br/><br/>
          <span style="color:red;">
            <a href="http://xiaoshevip.javaeye.com/blog/172867#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/138' target='_blank'><span style="color:red;font-weight:bold;">加入阿里巴巴，发展潜力无限</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 17 Mar 2008 10:50:11 +0800</pubDate>
        <link>http://xiaoshevip.javaeye.com/blog/172867</link>
        <guid>http://xiaoshevip.javaeye.com/blog/172867</guid>
      </item>
          <item>
        <title>反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)--转载 </title>
        <author>xiaoshevip</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xiaoshevip.javaeye.com">xiaoshevip</a>&nbsp;
                    链接：<a href="http://xiaoshevip.javaeye.com/blog/170347" style="color:red;">http://xiaoshevip.javaeye.com/blog/170347</a>&nbsp;
          发表时间: 2008年03月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div style="text-align: left">&nbsp;&nbsp; 其实AOP的意思就是面向切面编程.</div><br />&nbsp;&nbsp; OO注重的是我们解决问题的方法(封装成Method),而AOP注重的是许多解决解决问题的方法中的共同点,是对OO思想的一种补充!<br />&nbsp;&nbsp; 还是拿人家经常举的一个例子讲解一下吧:<br />&nbsp;&nbsp; 比如说,我们现在要开发的一个应用里面有很多的业务方法,但是,我们现在要对这个方法的执行做全面监控,或部分监控.也许我们就会在要一些方法前去加上一条日志记录,我们写个例子看看我们最简单的解决方案<br />&nbsp;&nbsp;&nbsp; 我们先写一个接口IHello.java代码如下:<br /><pre name="code" class="java">package sinosoft.dj.aop.staticaop;
 
 public interface IHello {
     /** *//**
      * 假设这是一个业务方法
      * @param name
      */
     void sayHello(String name);
 }
</pre>里面有个方法,用于输入"Hello" 加传进来的姓名;我们去写个类实现IHello接口<br /><pre name="code" class="java">package sinosoft.dj.aop.staticaop;

public class Hello implements IHello {

    public void sayHello(String name) {
        System.out.println("Hello " + name);
    }

}</pre><br /><br />&nbsp;&nbsp; 现在我们要为这个业务方法加上日志记录的业务,我们在不改变原代码的情况下,我们会去怎么做呢?也许,你会去写一个类去实现IHello接口,并依赖Hello这个类.代码如下:<br /><pre name="code" class="java"> package sinosoft.dj.aop.staticaop;
 
 public class HelloProxy implements IHello {
     private IHello hello;
 
     public HelloProxy(IHello hello) {
         this.hello = hello;
     }
 
    public void sayHello(String name) {
        Logger.logging(Level.DEBUGE, "sayHello method start.");
        hello.sayHello(name);
        Logger.logging(Level.INFO, "sayHello method end!");

    }

}
</pre>其中.Logger类和Level枚举代码如下:<br /><pre name="code" class="java">Logger.java
 package sinosoft.dj.aop.staticaop;
 
 import java.util.Date;
 
 public class Logger{
     /** *//**
      * 根据等级记录日志
      * @param level
      * @param context
     */
    public static void logging(Level level, String context) {
        if (level.equals(Level.INFO)) {
            System.out.println(new Date().toLocaleString() + " " + context);
        }
        if (level.equals(Level.DEBUGE)) {
            System.err.println(new Date() + " " + context);
        }
    }

}</pre>21Level.java<br /><br /><pre name="code" class="java">package sinosoft.dj.aop.staticaop;

public enum Level {
    INFO,DEBUGE;
}</pre>那我们去写个测试类看看,代码如下:<br /><pre name="code" class="java">Test.java
package sinosoft.dj.aop.staticaop;

public class Test {
   public static void main(String[] args) {
       IHello hello = new HelloProxy(new Hello());
       hello.sayHello("Doublej");
   }
}</pre>运行以上代码我们可以得到下面结果:<br /><br /><div class="quote_title">引用</div><div class="quote_div">Tue Mar 04 20:57:12 CST 2008 sayHello method start.<br />Hello Doublej<br />2008-3-4 20:57:12 sayHello method end!</div>从上面的代码我们可以看出,hello对象是被HelloProxy这个所谓的代理态所创建的.这样,如果我们以后要把日志记录的功能去掉.那我们只要把得到hello对象的代码改成以下:<br /><pre name="code" class="java">package sinosoft.dj.aop.staticaop;

public class Test {
    public static void main(String[] args) {
        IHello hello = new Hello();
        hello.sayHello("Doublej");
    }
}
</pre>上面代码,可以说是AOP最简单的实现!<br />&nbsp;&nbsp; 但是我们会发现一个问题,如果我们像Hello这样的类很多,那么,我们是不是要去写很多个HelloProxy这样的类呢.没错,是的.其实也是一种很麻烦的事.在jdk1.3以后.jdk跟我们提供了一个API&nbsp;&nbsp; java.lang.reflect.InvocationHandler的类. 这个类可以让我们在JVM调用某个类的方法时动态的为些方法做些什么事.让我们把以上的代码改一下来看看效果.<br />同样,我们写一个IHello的接口和一个Hello的实现类.在接口中.我们定义两个方法;代码如下 :<br /><br /><pre name="code" class="java">IHello.java
 package sinosoft.dj.aop.proxyaop;
 
 public interface IHello {
     /** *//**
      * 业务处理A方法
      * @param name
      */
     void sayHello(String name);
     /** *//**
     * 业务处理B方法
     * @param name
     */
    void sayGoogBye(String name);
}
</pre><br /><br /><pre name="code" class="java">Hello.java 

 package sinosoft.dj.aop.proxyaop;
 
 public class Hello implements IHello {
 
     public void sayHello(String name) {
         System.out.println("Hello " + name);
     }
     public void sayGoogBye(String name) {
         System.out.println(name+" GoodBye!");
    }
}
</pre>我们一样的去写一个代理类.只不过.让这个类去实现java.lang.reflect.InvocationHandler接口,代码如下:<br /><pre name="code" class="java"> package sinosoft.dj.aop.proxyaop;
 
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 
 public class DynaProxyHello implements InvocationHandler {
 
     /** *//**
     * 要处理的对象(也就是我们要在方法的前后加上业务逻辑的对象,如例子中的Hello)
     */
    private Object delegate;

    /** *//**
     * 动态生成方法被处理过后的对象 (写法固定)
     * 
     * @param delegate
     * @param proxy
     * @return
     */
    public Object bind(Object delegate) {
        this.delegate = delegate;
        return Proxy.newProxyInstance(
                this.delegate.getClass().getClassLoader(), this.delegate
                        .getClass().getInterfaces(), this);
    }
    /** *//**
     * 要处理的对象中的每个方法会被此方法送去JVM调用,也就是说,要处理的对象的方法只能通过此方法调用
     * 此方法是动态的,不是手动调用的
     */
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result = null;
        try {
            //执行原来的方法之前记录日志
            Logger.logging(Level.DEBUGE, method.getName() + " Method end .");
            
            //JVM通过这条语句执行原来的方法(反射机制)
            result = method.invoke(this.delegate, args);
            //执行原来的方法之后记录日志
            Logger.logging(Level.INFO, method.getName() + " Method Start!");
        } catch (Exception e) {
            e.printStackTrace();
        }
        //返回方法返回值给调用者
        return result;
    }

}
</pre>上面类中出现的Logger类和Level枚举还是和上一上例子的实现是一样的.这里就不贴出代码了.<br /><br />让我们写一个Test类去测试一下.代码如下:<br /><pre name="code" class="java">Test.java
 package sinosoft.dj.aop.proxyaop;
 
 public class Test {
     public static void main(String[] args) {
         IHello hello = (IHello)new DynaProxyHello().bind(new Hello());
         hello.sayGoogBye("Double J");
         hello.sayHello("Double J");
         
     }
}
</pre>运行输出的结果如下:<br /><div class="quote_title">引用</div><div class="quote_div">Tue Mar 04 21:24:03 CST 2008 sayGoogBye Method end .<br />Double J GoodBye!<br />2008-3-4 21:24:03 sayGoogBye Method Start!<br />Tue Mar 04 21:24:03 CST 2008 sayHello Method end .<br />Hello Double J<br />2008-3-4 21:24:03 sayHello Method Start!</div>由于线程的关系,第二个方法的开始出现在第一个方法的结束之前.这不是我们所关注的!<br />&nbsp;&nbsp; 从上面的例子我们看出.只要你是采用面向接口编程,那么,你的任何对象的方法执行之前要加上记录日志的操作都是可以的.他(DynaPoxyHello)自动去代理执行被代理对象(Hello)中的每一个方法,一个java.lang.reflect.InvocationHandler接口就把我们的代理对象和被代理对象解藕了.但是,我们又发现还有一个问题,这个DynaPoxyHello对象只能跟我们去在方法前后加上日志记录的操作.我们能不能把DynaPoxyHello对象和日志操作对象(Logger)解藕呢?<br />&nbsp;&nbsp; 结果是肯定的.让我们来分析一下我们的需求.<br />我们要在被代理对象的方法前面或者后面去加上日志操作代码(或者是其它操作的代码),那么,我们可以抽象出一个接口,这个接口里就只有两个方法,一个是在被代理对象要执行方法之前执行的方法,我们取名为start,第二个方法就是在被代理对象执行方法之后执行的方法,我们取名为end .接口定义如下 :<br /><pre name="code" class="java"> package sinosoft.dj.aop.proxyaop;
 
 import java.lang.reflect.Method;
 
 public interface IOperation {
     /** *//**
      * 方法执行之前的操作
      * @param method
     */
    void start(Method method);
    /** *//**
     * 方法执行之后的操作
     * @param method
     */
    void end(Method method);
}
</pre>我们去写一个实现上面接口的类.我们把作他真正的操作者,如下面是日志操作者的一个类:<br /><pre name="code" class="java">LoggerOperation.java
package sinosoft.dj.aop.proxyaop;

import java.lang.reflect.Method;

public class LoggerOperation implements IOperation {

    public void end(Method method) {
        Logger.logging(Level.DEBUGE, method.getName() + " Method end .");
    }

    public void start(Method method) {
        Logger.logging(Level.INFO, method.getName() + " Method Start!");
    }

}</pre><br /><br />&nbsp;&nbsp; 然后我们要改一下代理对象DynaProxyHello中的代码.如下:<br /><pre name="code" class="java"> package sinosoft.dj.aop.proxyaop;
 
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 
 public class DynaProxyHello implements InvocationHandler {
     /** *//**
      * 操作者
     */
    private Object proxy;
    /** *//**
     * 要处理的对象(也就是我们要在方法的前后加上业务逻辑的对象,如例子中的Hello)
     */
    private Object delegate;

    /** *//**
     * 动态生成方法被处理过后的对象 (写法固定)
     * 
     * @param delegate
     * @param proxy
     * @return
     */
    public Object bind(Object delegate,Object proxy) {
        
        this.proxy = proxy;
        this.delegate = delegate;
        return Proxy.newProxyInstance(
                this.delegate.getClass().getClassLoader(), this.delegate
                        .getClass().getInterfaces(), this);
    }
    /** *//**
     * 要处理的对象中的每个方法会被此方法送去JVM调用,也就是说,要处理的对象的方法只能通过此方法调用
     * 此方法是动态的,不是手动调用的
     */
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result = null;
        try {
            //反射得到操作者的实例
            Class clazz = this.proxy.getClass();
            //反射得到操作者的Start方法
            Method start = clazz.getDeclaredMethod("start",
                    new Class[] { Method.class });
            //反射执行start方法
            start.invoke(this.proxy, new Object[] { method });
            //执行要处理对象的原本方法
            result = method.invoke(this.delegate, args);
//            反射得到操作者的end方法
            Method end = clazz.getDeclaredMethod("end",
                    new Class[] { Method.class });
//            反射执行end方法
            end.invoke(this.proxy, new Object[] { method });

        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

}</pre>然后我们把Test.java中的代码改一下.测试一下:<br /><pre name="code" class="java">package sinosoft.dj.aop.proxyaop;

public class Test {
    public static void main(String[] args) {
        IHello hello = (IHello)new DynaProxyHello().bind(new Hello(),new LoggerOperation());
        hello.sayGoogBye("Double J");
        hello.sayHello("Double J");
        
    }
}</pre>结果还是一样的吧.<br /><br />&nbsp;&nbsp; 如果你想在每个方法之前加上日志记录,而不在方法后加上日志记录.你就把LoggerOperation类改成如下:<br /> <pre name="code" class="java">package sinosoft.dj.aop.proxyaop;
 
 import java.lang.reflect.Method;
 
 public class LoggerOperation implements IOperation {
 
     public void end(Method method) {
         //Logger.logging(Level.DEBUGE, method.getName() + " Method end .");
     }

    public void start(Method method) {
        Logger.logging(Level.INFO, method.getName() + " Method Start!");
    }

}</pre>运行一下.你就会发现,每个方法之后没有记录日志了. 这样,我们就把代理者和操作者解藕了!<br /><br />&nbsp;&nbsp; 下面留一个问题给大家,如果我们不想让所有方法都被日志记录,我们应该怎么去解藕呢.?<br />我的想法是在代理对象的public Object invoke(Object proxy, Method method, Object[] args)方法里面加上个if(),对传进来的method的名字进行判断,判断的条件存在XML里面.这样我们就可以配置文件时行解藕了.如果有兴趣的朋友可以把操作者,被代理者,都通过配置文件进行配置 ,那么就可以写一个简单的SpringAOP框架了.
          <br/><br/>
          <span style="color:red;">
            <a href="http://xiaoshevip.javaeye.com/blog/170347#comments" style="color:red;">已有 <strong>1</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/138' target='_blank'><span style="color:red;font-weight:bold;">加入阿里巴巴，发展潜力无限</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 12 Mar 2008 09:34:13 +0800</pubDate>
        <link>http://xiaoshevip.javaeye.com/blog/170347</link>
        <guid>http://xiaoshevip.javaeye.com/blog/170347</guid>
      </item>
          <item>
        <title>乐理常识-调式区分</title>
        <author>xiaoshevip</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xiaoshevip.javaeye.com">xiaoshevip</a>&nbsp;
                    链接：<a href="http://xiaoshevip.javaeye.com/blog/128453" style="color:red;">http://xiaoshevip.javaeye.com/blog/128453</a>&nbsp;
          发表时间: 2007年09月30日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          简单的说C大调中的C是指这个调式中的稳定因为C，然后将C当作1（大调中的一级音），,构成音阶1234567，这就是C大调的调式音阶，在C大调的音乐中，乐曲是以那7个音位基本音级而构成的。 <br />
<br />
c小调，同样的调式中的稳定因为c，然后把c当作6（小调中的一级音），构成音阶6712345，在c小调的音乐中，乐曲是以那7个音位基本音级而构成的。 <br />
<br />
大调的色彩明亮，坚定，小调的色彩，柔和，暗淡。 <br />
<br />
以上说的只是自然大调和自然小调，这两种是比较常见的。 <br />
<br />
和声大调，6（六级音）要降低半音，旋律大调，但旋律位下行时6，7（六，七级音）都要见的半音。 <br />
<br />
和声小调，5（七级音）要升高半音，旋律小调，4，5（六七级音）要升高半音。 <br />
<br />
自然大小调的特征： <br />
<br />
一级音与三级音的大小：大调中，一级音与三级音的关系是大三度，小调中，一级音与三级以的关系是小三度。 <br />
<br />
大调式的音乐在曲中的时候通常会以1位结束音，比如《义勇军进行曲》，所以的音阶的I级是1。小调的的稳定音机6，所以小调歌曲通常结束在6音上，如《莫斯科郊外的晚上》。 <br />
如果还不明了，可以做个表 <br />
<br />
自然大调：do re mi fa sol la si do <br />
自然小调：la si do re mi fa sol la <br />
音级标记：I II III IV V VI VII I <br />
<br />
不论哪种调式，都要把调式中最稳定的音作为I级音，调式音阶要从I级音唱起，大调从do开始，小调从la开始。 <br />
<br />
还有民族调式的，我已经在另一个问题中答到了。 <br />
<br />
关于调式名 <br />
<br />
C大调的C是在说I级音在C这个位置，大调则表示它的结构，I级音（do）与III级音mi是大三度关系。 <br />
a小调的a是在说I级音在a这个位置，小调则是在说它的I级音（la）与III级音（do）的关系是小三度。 <br />
<br />
关于和声大小调，旋律大小调，我的另一个回答中已经提及，如果还不明白，可以去买本乐理书读读，毕竟有些东西我打不出来 <br />
<br />
讲得不大好理解，这就是我的功夫不深了。 <br />
<br />
<br />
关于五声调式： <br />
<br />
中国的五声调式 <br />
<br />
&ldquo;宫商角徵羽&rdquo;分别对应简谱中的12356 <br />
<br />
当乐曲的稳定音为宫音时，这个乐曲的调式叫做宫调式，又比如宫音是C，那么它的完整名称叫做C宫调，余类推。 <br />
<br />
宫调式有大调色彩，羽调式有小调色彩，但是在音级个数上有所区别。 <br />
<br />
解释这个问题，首先要说明&ldquo;唱名&rdquo;和&ldquo;音名&rdquo;两个体系。音乐当中，唱名，顾名思义，指唱谱时所用的音符的名称，即1234567（do re mi fa sol la si）。而音名是音乐中的各音自己的名称，用字母命名，分别为CDEFGAB。 <br />
<br />
下面开始解释这个问题，要看仔细，想清楚啊，不然可能会有点乱。 <br />
<br />
12345671，一个八度的八个音，各音之音的关系并不相同，分为全音和半音两种，34之间和71之间是半音，其它相邻两音间是全音，所以，12345671构成了全全半全全全半的关系。像这样的关系构成的一个音阶，我们称之为（自然）大调音阶，其中1(do)叫做主音。 <br />
<br />
1234567，也就是唱名，并不包含有绝对音高的信息，说白了，它们是可以游移的。就好像唱同样的歌，有的人唱得高，有的人唱得低，大家高度可以不同。1234567这样一个音阶也是一样，从任意高度起唱1（do），都是可以的。我唱和你唱大多时候会不一样。 <br />
<br />
然而，音名则不同。CDEFGAB作为各音自己的名称，是与绝对音高挂勾的，不是随便定的，我说do，无法确定它是多高，但我说D，就可以确定它是多高。音名与绝对音高相关。比如标准音A，其频率是440Hz，这是固定的，国际公认的。有一个固定频率，就有一个固定的音高。到什么地方，A也是这么高。 <br />
<br />
把以上两部分相叠加，就有了调。由于大家都唱唱名，1234567因为音高可以不同，就有无数组，那么如何来统一呢？假如我们规定，1234567中的1（do，即大调主音）唱C音这个高度，后面的其它音按照大调的关系：全全半全全全半，依次往下排。这样就建立了一个以C音高度为1（do）的大调音阶，于是就有了C大调。如果以D音为1（do）起，按照大调音阶的关系建立一个音阶，我们就称之为D大调。 <br />
<br />
简而言之，什么叫C大调？以C为do就是C大调，同理，以D为do就是D大调，即：一个调式音阶的主音在什么音上，就是什么音的调。所以，不同的调之间的第一个区别就是各调音阶所在的音高不同，形象地说，张宇要唱孙楠的歌，肯定和孙楠不在一个调上。 <br />
<br />
也许你还会问，什么是D小调呢？上面说了，一个调式（此处先不展开说调式，你可以在此简单理解为大调小调等这些东西叫做调式，每种调式都有一个主音）的主音在X音上，就称为X大（小）调。所以说，以&ldquo;D小调&rdquo;为例，我们可以分成两部分来看，&ldquo;D&rdquo;是主音的高度，&ldquo;小调&rdquo;是调式的标记。前面说过大调式的各音之音的关系，是全全半全全全半，（自然）小调式与之不同，是全半全全半全全，类似于67123456（la si do re mi fa sol la）的关系。这种情况下，6是主音。所以，D小调可以简单理解为：以D音为6（la）的调。 <br />
<br />
由于C大调是最最基础的调，在C大调的情况下（注意这句话），1234567和CDEFGAB一一对应，不需要有任何变化记号，CDEFGAB就可以天然地满足1234567之间所要求的全全半全全全半的关系，因此，C大调是最自然的大调。学调的时候，总是从C大调开始，因此，许多人有一个错误的观念，C就是do，do就是C，有许多初学某种乐器的朋友都会问一个问题：do在哪儿啊？如果问到我，我总是回答，哪儿都是，随便。原因在上面已经解释了，do是不固定的。看一眼上面我说要注意的那句话，只有在C大调的情况下，才能说C是do，否则，do到处都是。 另外，2/4和4/4都是四分音节为一拍, 2/4是2拍为一小节,4/4是4拍为一小节。<br />
          <br/><br/>
          <span style="color:red;">
            <a href="http://xiaoshevip.javaeye.com/blog/128453#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/138' target='_blank'><span style="color:red;font-weight:bold;">加入阿里巴巴，发展潜力无限</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 30 Sep 2007 13:23:12 +0800</pubDate>
        <link>http://xiaoshevip.javaeye.com/blog/128453</link>
        <guid>http://xiaoshevip.javaeye.com/blog/128453</guid>
      </item>
          <item>
        <title>35岁前必成功的12级跳(男女通用) </title>
        <author>xiaoshevip</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xiaoshevip.javaeye.com">xiaoshevip</a>&nbsp;
                    链接：<a href="http://xiaoshevip.javaeye.com/blog/124897" style="color:red;">http://xiaoshevip.javaeye.com/blog/124897</a>&nbsp;
          发表时间: 2007年09月18日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font size="2"><font face="Arial">第1跳:1个目标  <br />
一艘没有航行目标的船，任何方向的风都是逆风，请明确以下几点： <br />
1. 你为什么是穷人 &mdash;&mdash; 很多时候是因为你没有立下成为富人的目标。 <br />
2. 你的人生核心目标是什么 &mdash;&mdash; 杰出人士与平庸之辈的根本差别，并不是天赋、机遇，而在于有无目标。 <br />
3. 起跑领先一步，人生领先一大步：成功从选定目标开始。 <br />
4. 贾金斯式的人永远不会成功 &mdash;&mdash; 为什么大多数人没有成功？真正能完成自己计划的人只有5%，大多数人不是将自己的目标舍弃，就是沦为缺乏行动的空想。 <br />
5. 如果你想在35岁以前成功，你一定得在25～30岁之间确立好你的人生目标。 <br />
6. 每日、每月、每年都要问自己：我是否达到了自己定下的目标？ </font>&nbsp;</font></p>
<p><br />
<font size="2">第2跳：2个成功基点 <br />
站好位置，调正心态，努力冲刺，35岁以前成功。 <br />
（一）人生定位 <br />
1. 人怕入错行：你的核心竞争力是什么？ <br />
2. 成功者找方法，失败者找借口。 <br />
3. 从三百六十行中选择你的最爱：很多时候兴趣所在是成功的动力。人人都可以创业，但却不是人人都能创业成功。 <br />
4. 寻找自己的黄金宝地。 <br />
（二）永恒的真理：心态决定命运，35岁以前的心态将决定你一生的命运。 <br />
1. 不满现状的人才能成为富翁 &mdash;&mdash; 能追不尽景，始是不凡人。 <br />
2. 敢于梦想，勇于梦想 &mdash;&mdash; 这个世界永远属于追梦的人。 <br />
3. 35 岁以前不要怕，35岁以后不要悔。 <br />
4. 出身贫民，并非一辈子是贫民，只要你永远保持一颗进取的心 &mdash;&mdash; 举目远望，中国成功人士很多来自小地方。 <br />
5. 做一个积极的思维者。 <br />
6. 不要败给悲观的自己。 <br />
有的人比你富有一千倍，他们也会比你聪明一千倍么？不会，他们只是年轻时心气比你高一千倍。 人生的好多次失败，最后并不是败给别人，而是败给了悲观的自己。 <br />
7. 成功者不过是爬起来比倒下去多一次 <br />
8. 宁可去碰壁，也不要在家里面壁 <br />
　　克服你的失败、消极的心态 &mdash;&mdash; 找个地方喝点酒，或找个迪厅跳跳舞，或找帮朋友侃侃而谈，然后，积极行动起来。 </font></p>
<p><br />
<font size="2">第3跳：3大技巧 <br />
1. 管理时间：你的时间在哪里，你的成就就在哪里。 <br />
一个把1小时看成60分钟的人，比一个将之看作一小时的人的时间，要多60倍。 <br />
2. 你不理财，财不理你。 <br />
3. 自我管理，游刃有余 &mdash;&mdash; 创业不怕本小，脑子一定要好；可以考虑开家特色店；做别人不愿做的生意。 </font></p>
<p><br />
<font size="2">第4跳：4项安身立命的理念 <br />
35 岁以前一定要形成个人风格，正如小天后蔡依林所唱：要有属于你自己的招牌动作。 <br />
1. 做人优于做事。 <br />
做事失败可以重来，做人失败却不能重来：做人要讲义气；做事永不气馁。 <br />
2. 豁达的男人有财运，所以，35岁前请搞定你的婚姻生活 &mdash;&mdash; 找个豁达的男人做老公吧！ <br />
3. 忠诚的原则：35岁前你还没有建立起忠诚美誉，这一缺点将要困扰你一生。 <br />
4. 把小事做细，但不要耍小聪明 &mdash;&mdash; 中国人想做大事的人太多，而愿把小事做完美的人太少。 </font></p>
<p><br />
<font size="2">第5跳：5分运气  <br />
比尔?盖茨说：人生是不公平的，习惯去接受它吧！ <br />
1. 人生的确有很多运气的成分：谋事在人，成事在天。 <br />
2. 机会时常意外地降临，但常常属于那些决不放弃的人。 <br />
3. 抓住人生的每一次机会 &mdash;&mdash; 机会就像一只小鸟，如果你不抓住，它就会飞得无影无踪。 <br />
4. 智者早一步，愚者晚一步。 </font></p>
<p><br />
<font size="2">第6跳：6项要求 <br />
1. 智慧：别人可你以拿走你的一切，但拿不走你的智慧；巧妙运用自己的智慧。 <br />
2. 勇气：勇气的力量有时会让你成为 &ldquo; 超人 &rdquo; ；敢于放弃，敢于 &ldquo; 舍得 &rdquo; 。 <br />
3. 培养自己的 &ldquo; 领导才能、领袖气质 &rdquo;&mdash;&mdash; 有机会一定要登顶 &ldquo; 振臂一呼，应者云集 &rdquo; 的境地。 <br />
4. 创造性：不要做循规蹈矩的人。25～35岁是人生最有创造性的阶段，很多成功人士也都产生在这一阶段。 <br />
5. 明智：知道自己的长处、短处，定向聚焦；尽量在自己的熟悉的领域努力。 <br />
6. 持之以恒的行动力：在你选定的行业坚持十年，你一定会有机会笑到最后。 </font></p>
<p><br />
<font size="2">第7跳：7分学习 <br />
1. 知识改变命运。 <br />
2.35 岁前学会你行业中必要的一切知识 &mdash;&mdash; 每天淘汰你自己；在商言商；太相信书本的人，只能成为打工仔。 <br />
3. 思考、实践，再思考、再实践。 </font></p>
<p><br />
<font size="2">第8跳：8分交际 <br />
朋友多了路好走： <br />
1. 智商很重要，情商更重要：35岁前请务必建立起人际关系网。 <br />
2. 人脉即财脉。 <br />
3. 交友有原则。 <br />
4. 善于沟通：35岁前一定要锻炼出自己的演讲才能，很多成功人士首先是个出色的演说家。 </font></p>
<p><br />
<font size="2">第9跳：9分习惯 <br />
习惯的力量是惊人的，35岁前养成的习惯决定着你的成功的大小。 <br />
1. 积极思维的好习惯。 <br />
2. 养成高效工作的好习惯 &mdash;&mdash; 学会喜欢并习惯你的办公室；生活可以不拘小节，但工作一定要谨小慎微；学习聆听，不打断别人说话。 <br />
3. 养成锻炼身体的好习惯。 <br />
4. 广泛爱好的好习惯。 <br />
5. 快速行动的好习惯。 </font></p>
<p><br />
<font size="2">第10跳：10分自信 <br />
1. 自信是成功的精神支柱。 <br />
2. 自信方能赢得别人的信任。 <br />
3. 把自信建立在创造价值的基础上。 <br />
4. 如何建立自信 &mdash;&mdash; 为自己确立目标；发挥自己的长处；做事有计划、不拖拉、不轻言放弃；学会自我激励；坚持做你自己。 </font></p>
<p><br />
<font size="2">第11跳 11个需要避开的成功陷阱 <br />
1. 只有功劳，没有苦劳； <br />
2. 不要 &ldquo; 怀才不遇 &rdquo; ，而要寻找机遇； <br />
3. 不要想发横财； <br />
4. 不要为钱而工作，而让钱为你工作； <br />
5. 盲目跟风，人云亦云，人做我也做； <br />
6. 小富即安，不思进取，知足常乐； <br />
7. 承认错误而非掩饰错误； <br />
8. 脚踏实地而非想入非非； <br />
9. 野心太大而不是信心十足； <br />
10. 反复跳槽不可取； <br />
11. 眼高手低；不择手段。 </font></p>
<p><br />
<font size="2">第12跳 12分努力 <br />
没有人能随随便便成功： <br />
1. 小不是成功，大不是成功，由小变大才是成功； <br />
2. 中国社会进入微利时代：巧干+敢干+实干=成功； <br />
3. 努力尝试就有成功的可能； <br />
4. 做任何事情，尽最大努力； <br />
5. 把事情当成事业来做； <br />
6. 争取早日掘到人生的第一桶金。 </font></p>
<p><font size="2">&nbsp;</font></p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://xiaoshevip.javaeye.com/blog/124897#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/138' target='_blank'><span style="color:red;font-weight:bold;">加入阿里巴巴，发展潜力无限</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 18 Sep 2007 10:12:34 +0800</pubDate>
        <link>http://xiaoshevip.javaeye.com/blog/124897</link>
        <guid>http://xiaoshevip.javaeye.com/blog/124897</guid>
      </item>
          <item>
        <title>未婚男女要看的20条军规</title>
        <author>xiaoshevip</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xiaoshevip.javaeye.com">xiaoshevip</a>&nbsp;
                    链接：<a href="http://xiaoshevip.javaeye.com/blog/120532" style="color:red;">http://xiaoshevip.javaeye.com/blog/120532</a>&nbsp;
          发表时间: 2007年09月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p style="TEXT-INDENT: 2em">1.不要因为寂寞去<clk></clk>恋爱，<nobr oncontextmenu="return false;" id="key3" onmousemove="kwM(5);" onmouseover="kwE(event,5, this);" onclick="return kwC();" target="_blank" onmouseout="kwL(event, this);" style="COLOR: #6600ff; BORDER-BOTTOM: 0px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline">时间</nobr>是魔鬼，天长日久，如果你是个多情的人，即使不爱对方，到时也会产生感情，最后你怎么办？ </p>
<p style="TEXT-INDENT: 2em">2.不要为了负责而去结婚，要知道，不爱对方却和对方结婚是最不负责的。即使当时让对方很伤心，但是总比让他几年甚至一辈子伤心强。 </p>
<p style="TEXT-INDENT: 2em">3.不管多大多老，不<clk></clk><nobr oncontextmenu="return false;" id="key7" onmousemove="kwM(10);" onmouseover="kwE(event,10, this);" onclick="return kwC();" target="_blank" onmouseout="kwL(event, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline">管家</nobr>人怎么催，都不能随便对待婚姻，婚姻不是打牌，重新洗牌是要付出代价的。 </p>
<p style="TEXT-INDENT: 2em">4.感情的事基本上没有谁对谁错，他（她）要离开你，总是有什么地方不能令他（她）满足，回头想想，过去在一起的日子，总是美好的。当然卑劣的感情骗子也有，不过这样的人极少数。 </p>
<p style="TEXT-INDENT: 2em">5.和一个人生活习惯有很大差距的人恋爱不要紧，<clk></clk><nobr oncontextmenu="return false;" id="key6" onmousemove="kwM(8);" onmouseover="kwE(event,8, this);" onclick="return kwC();" target="_blank" onmouseout="kwL(event, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline">结婚</nobr>要慎重，想想你是否可以长久受的住彼此的不同。 </p>
<p style="TEXT-INDENT: 2em">6.有人说恋爱要找自己喜欢的人，结婚要找喜欢自己的人，都是片面的。恋人不喜欢自己有什么可恋？老婆自己不喜欢怎么过一辈子？ </p>
<p style="TEXT-INDENT: 2em">7.真爱一个人，就要尽量让他开心，他开心了，你不就开心了，那么双方就有激情了。 </p>
<p style="TEXT-INDENT: 2em">8.不要因为长相不如对方而放弃追求的打算，长相只是一时的印象，真正决定能否结合主要取决于双方的性格。你是不是见过很多帅哥配丑女，<nobr oncontextmenu="return false;" id="key1" onmousemove="kwM(1);" onmouseover="kwE(event,1, this);" onclick="return kwC();" target="_blank" onmouseout="kwL(event, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline">美女</nobr>配丑男？这其中自然有很多的原因和理由的。 </p>
<p style="TEXT-INDENT: 2em">9.女人要学会扮靓，美点总是好的，要懂得<clk></clk>时尚，不懂你就不是一个完整的女人。 </p>
<p style="TEXT-INDENT: 2em">10.恋爱的时间能长尽量长。这最少有两点好处：一、充分尽可能长的享受恋爱的愉悦，婚姻和恋爱的感觉总是不同的吧&hellip;；二、两个人相处时间越长，越能检验彼此是否真心，越能看出两个人的性格是否合得来。这样婚后的感情就会牢固的多。 </p>
<p style="TEXT-INDENT: 2em">11.男人不坏，<nobr oncontextmenu="return false;" id="key4" onmousemove="kwM(6);" onmouseover="kwE(event,6, this);" onclick="return kwC();" target="_blank" onmouseout="kwL(event, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline">女人</nobr>不爱。这坏不是指心肠狠，自私无情什么的。而是指油嘴滑舌，轻浮肉麻的表现，所以不要不愿去做。对别人这样说不对，可对自己的老婆、恋爱就不同，就要油嘴滑舌点。为什么不能做个心好嘴滑的男人呢？ </p>
<p style="TEXT-INDENT: 2em">12.都说婚姻是爱情的坟墓，那是因为你在婚前就已经往那个坟墓的方向走着了。就算不结婚，也会在坟墓前分手。为什么不先分手，而硬是一头钻进坟墓？ </p>
<p style="TEXT-INDENT: 2em">13.只会扮靓的女人是一具花瓶，只会读书的女人是一本字典。服饰<clk></clk><nobr oncontextmenu="return false;" id="key5" onmousemove="kwM(7);" onmouseover="kwE(event,7, this);" onclick="return kwC();" target="_blank" onmouseout="kwL(event, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline">美容</nobr>是做一个女人的必要条件，但不是充要条件。你还要多看书，这样你会发现生活是多么的美好。 </p>
<p style="TEXT-INDENT: 2em">14.平平淡淡才是真，没错，可那应该是激-情过后的平淡，然后再起激-情，再有平淡。波浪形式的交替出现，生活才会美好，才更有意义。 </p>
<p style="TEXT-INDENT: 2em">15.你爱他吗？爱就告诉他，何必把思念之苦藏在心底深处，爱一个人不是什么错，它是美好的。 </p>
<p style="TEXT-INDENT: 2em">16.老婆和老妈掉进河里，我会先救老妈，因为她给了我生命，我找不出任何理由丢下她不管。老婆如果没救上来，我可以再给她陪葬，在墓里继续我们的<clk></clk>爱情。 </p>
<p style="TEXT-INDENT: 2em">17.草率的结婚已经是错了，就不要草率的去离婚。真的不行再离也不迟。 </p>
<p style="TEXT-INDENT: 2em">18.经常听说男人味和女人味，你知道男人味是什么味道，女人味又是一种什么味道吗？男人味就是豁达勇敢，女人味就是温柔体贴。 </p>
<p style="TEXT-INDENT: 2em">19.<clk></clk><nobr oncontextmenu="return false;" id="key0" onmousemove="kwM(0);" onmouseover="kwE(event,0, this);" onclick="return kwC();" target="_blank" onmouseout="kwL(event, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline">魅力</nobr>是什么？魅力不是漂亮，漂亮的女人不一定就能吸引男人的眼光，端庄幽雅的女人男人更喜欢。所以不要担心不够漂亮。 </p>
<p style="TEXT-INDENT: 2em">20.初恋都是难忘的，觉得美好。为什么？不是因为他（她）长的很帅或很漂亮，也不是因为得不到的就是好的。而是因为人初涉爱情时，心里异常纯真，绝无私心杂念，只知道倾己所有去爱对方。而以后的爱情可能就没那么纯真无暇了，纯真是人世间最为可贵的东西。好好的珍惜吧。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://xiaoshevip.javaeye.com/blog/120532#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/138' target='_blank'><span style="color:red;font-weight:bold;">加入阿里巴巴，发展潜力无限</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 05 Sep 2007 09:24:43 +0800</pubDate>
        <link>http://xiaoshevip.javaeye.com/blog/120532</link>
        <guid>http://xiaoshevip.javaeye.com/blog/120532</guid>
      </item>
          <item>
        <title>程序员是如何喝酒的 </title>
        <author>xiaoshevip</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xiaoshevip.javaeye.com">xiaoshevip</a>&nbsp;
                    链接：<a href="http://xiaoshevip.javaeye.com/blog/114968" style="color:red;">http://xiaoshevip.javaeye.com/blog/114968</a>&nbsp;
          发表时间: 2007年08月21日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <font color="#003366">大家喝的是啤酒。这时你入座了。 <br />
你给自己倒了杯可乐，这叫低配置。 <br />
你给自已倒了杯啤酒，这叫标准配置。 <br />
你给自己倒了杯茶水，这茶的颜色还跟啤酒一样，这叫木马。 <br />
你给自己倒了杯可乐，还滴了几滴醋，不仅颜色跟啤酒一样，而且不冒热气还有泡泡，这叫超级木马。 <br />
你的同事给你倒了杯白酒，这叫推荐配置。 <br />
<br />
人到齐了，酒席开始了。 <br />
你先一个人喝了一小口，这叫单元测试。 <br />
你跟旁边的人说哥们咱们随意，这叫交叉测试。 <br />
但是他说不行，这杯要干了，这叫压力测试。 <br />
于是你说那就大家一起来吧，这叫内部测试。 <br />
这个时候boss向全场举杯了，这叫公开测试。 <br />
<br />
菜过三巡，你就不跟他们客气了。 <br />
你向对面的人敬酒，这叫p2p. <br />
你向对面的人敬酒，他回敬你，你又再敬他&hellip;&hellip;，这叫tcp. <br />
你向一桌人挨个敬酒，这叫令牌环。 <br />
你说只要是兄弟就干了这杯，这叫广播。 <br />
可是你的上司jj听了不高兴了，只有兄弟么，罚酒三杯。这叫炸弹。 <br />
可是你的下级mm听了不高兴了，我喝一口，你喝一杯，这叫恶意攻击。 <br />
有一个人过来向这桌敬酒，你说不行你先过了我这关，这叫防火墙。 <br />
你的小弟们过来敬你酒，这叫一对多。 <br />
你是boss，所有人过来敬你酒，这叫服务器。 <br />
<br />
酒是一样的，可是喝法是不同的。 <br />
你喝了一杯，boss喝了一口，这叫c#。 <br />
你喝了一杯，mm喝了一口，这叫vb。 <br />
你喝了一杯，你大哥喝了半杯，这叫c++。 <br />
你喝了半杯，你小弟喝了一杯，这叫汇编。 <br />
你喝了一杯，你的搭档也喝了一杯，这叫c。 <br />
<br />
酒是一样的，可是喝酒的人是不同的。 <br />
你越喝脸越红，这叫频繁分配释放资源。 <br />
你越喝脸越白，这叫资源不释放。 <br />
你已经醉了，却说我还能喝，叫做资源额度不足。 <br />
你明明能喝，却说我已经醉了，叫做资源保留。 <br />
你喝一段时间就上厕所，这叫cache。 <br />
<br />
酒过三巡，你也该活动活动了。 <br />
你一桌一桌的走，这叫轮巡。 <br />
你突然看到某一桌的漂亮mm，走了过去，这叫优先级。 <br />
你去了坐下来就不打算走了，这叫死循环。 <br />
你的老大举杯邀你过去，你只好过去，这叫激活事件。 <br />
你向一桌敬酒，他们说不行不行我们都喝白的，于是你也喝白的，这叫本地化。 <br />
你向boss敬酒，可是boss被围了起来，你只能站在外圈，这叫排队。 <br />
你终于到了内圈，小心翼翼的向前一步，这叫访问临界区。 <br />
你拍着boss的肩膀说哥们咱们喝一杯，这叫越界。 <br />
你不知喝了几圈了，只会说两个字，干了，这叫udp。 <br />
可是还有人拿着酒瓶跑过来说，刚才都没跟你喝，这叫丢包。 <br />
<br />
喝酒喝到最后的结果都一样 <br />
你突然跑向厕所，这叫捕获异常。 <br />
你在厕所吐了，反而觉得状态不错，这叫清空内存。 <br />
你在台面上吐了，觉得很惭愧，这叫程序异常。 <br />
你在boss面前吐了，觉得很害怕，这叫系统崩溃。 <br />
你吐到了boss身上，只能索性晕倒了，这叫硬件休克。</font>
          <br/><br/>
          <span style="color:red;">
            <a href="http://xiaoshevip.javaeye.com/blog/114968#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/138' target='_blank'><span style="color:red;font-weight:bold;">加入阿里巴巴，发展潜力无限</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 21 Aug 2007 19:20:46 +0800</pubDate>
        <link>http://xiaoshevip.javaeye.com/blog/114968</link>
        <guid>http://xiaoshevip.javaeye.com/blog/114968</guid>
      </item>
      </channel>
</rss>