2005年05月17日

db4o是一个纯面向对象的数据库系统,DB4O有.NET、MONO和Jave版本,全部用托管代码写成并且开放源代码。如果关注Mono的朋友应该注意到Mono中已经有个可选安装组件DB4O。可以从他们的网站http://www.db4o.com/下载源代码。

下面我简单来说一下DB4O的使用方法:

1.       定义对象

我们定义三个类,为的是测试DB4O处理对象间的关系。

People

Car

CarCollection

 

 

 

 

2.       保存对象

private void WriteDate()
        
{
            
//初始化对象数据
            People format=new People("format",true,DateTime.Now);
            format.Cars.AddCar(
new Car("format’s Car",CarColor.Blue));
            format.Cars.AddCar(
new Car("format’s Car 2",CarColor.Red));

            People bill
=new People("Bill",true,DateTime.Now);
            bill.Cars.AddCar(
new Car("bill’s Car",CarColor.Black));
            bill.Cars.AddCar(
new Car("bill’s Car",CarColor.Red));

            ObjectContainer db
=Db4o.openFile("formatData.yap");
            
try
            
{
                
// do something with db4o
                
//保存format和bill
                db.set(format);
                db.
set(bill);
            }

            
finally
            
{
                db.close();
            }


        }


private void WriteDate()
        
{
            
//初始化对象数据
            People format=new People("format",true,DateTime.Now);
            format.Cars.AddCar(
new Car("format’s Car",CarColor.Blue));
            format.Cars.AddCar(
new Car("format’s Car 2",CarColor.Red));

            People bill
=new People("Bill",true,DateTime.Now);
            bill.Cars.AddCar(
new Car("bill’s Car",CarColor.Black));
            bill.Cars.AddCar(
new Car("bill’s Car",CarColor.Red));

            ObjectContainer db
=Db4o.openFile("formatData.yap");
            
try
            
{
                
// do something with db4o
                
//保存format和bill
                db.set(format);
                db.
set(bill);
            }

            
finally
            
{
                db.close();
            }


        }


private void WriteDate()
        
{
            
//初始化对象数据
            People format=new People("format",true,DateTime.Now);
            format.Cars.AddCar(
new Car("format’s Car",CarColor.Blue));
            format.Cars.AddCar(
new Car("format’s Car 2",CarColor.Red));

            People bill
=new People("Bill",true,DateTime.Now);
            bill.Cars.AddCar(
new Car("bill’s Car",CarColor.Black));
            bill.Cars.AddCar(
new Car("bill’s Car",CarColor.Red));

            ObjectContainer db
=Db4o.openFile("formatData.yap");
            
try
            
{
                
// do something with db4o
                
//保存format和bill
                db.set(format);
                db.
set(bill);
            }

            
finally
            
{
                db.close();
            }


        }


private void WriteDate()
        
{
            
//初始化对象数据
            People format=new People("format",true,DateTime.Now);
            format.Cars.AddCar(
new Car("format’s Car",CarColor.Blue));
            format.Cars.AddCar(
new Car("format’s Car 2",CarColor.Red));

            People bill
=new People("Bill",true,DateTime.Now);
            bill.Cars.AddCar(
new Car("bill’s Car",CarColor.Black));
            bill.Cars.AddCar(
new Car("bill’s Car",CarColor.Red));

            ObjectContainer db
=Db4o.openFile("formatData.yap");
            
try
            
{
                
// do something with db4o
                
//保存format和bill
                db.set(format);
                db.
set(bill);
            }

            
finally
            
{
                db.close();
            }


        }


private void WriteDate()
        
{
            
//初始化对象数据
            People format=new People("format",true,DateTime.Now);
            format.Cars.AddCar(
new Car("format’s Car",CarColor.Blue));
            format.Cars.AddCar(
new Car("format’s Car 2",CarColor.Red));

            People bill
=new People("Bill",true,DateTime.Now);
            bill.Cars.AddCar(
new Car("bill’s Car",CarColor.Black));
            bill.Cars.AddCar(
new Car("bill’s Car",CarColor.Red));

            ObjectContainer db
=Db4o.openFile("formatData.yap");
            
try
            
{
                
// do something with db4o
                
//保存format和bill
                db.set(format);
                db.
set(bill);
            }

            
finally
            
{
                db.close();
            }


        }


3.       对象的简单查询

/// <summary>
        
/// 通过简单查询获得数据
        
/// </summary>

        private void ReadDate()
        
{
            ArrayList data
=new ArrayList();

            ObjectContainer db
=Db4o.openFile("formatData.yap");

            
//这里查寻Sex为true的对象
            People people = new People(null,true);//如果对象中的字段为null,那么就匹配所有数据
            
            ObjectSet result 
= db.get(people);
            
int legth=result.size();
            
try
            
{
                
// do something with db4o

                
//这里不知道是否是个BUG,我照文档上的用while循环,就outofMemory
                for(int i=0;i<legth;i++)
                
{
                    data.Add(result.next());
//把查询出的对象添加到ArrayList
                }

                
this.grdPeople.DataSource=data;
            
            }

            
finally
            
{
                db.close();
            }


/// <summary>
        
/// 通过简单查询获得数据
        
/// </summary>

        private void ReadDate()
        
{
            ArrayList data
=new ArrayList();

            ObjectContainer db
=Db4o.openFile("formatData.yap");

            
//这里查寻Sex为true的对象
            People people = new People(null,true);//如果对象中的字段为null,那么就匹配所有数据
            
            ObjectSet result 
= db.get(people);
            
int legth=result.size();
            
try
            
{
                
// do something with db4o

                
//这里不知道是否是个BUG,我照文档上的用while循环,就outofMemory
                for(int i=0;i<legth;i++)
                
{
                    data.Add(result.next());
//把查询出的对象添加到ArrayList
                }

                
this.grdPeople.DataSource=data;
            
            }

            
finally
            
{
                db.close();
            }


/// <summary>
        
/// 通过简单查询获得数据
        
/// </summary>

        private void ReadDate()
        
{
            ArrayList data
=new ArrayList();

            ObjectContainer db
=Db4o.openFile("formatData.yap");

            
//这里查寻Sex为true的对象
            People people = new People(null,true);//如果对象中的字段为null,那么就匹配所有数据
            
            ObjectSet result 
= db.get(people);
            
int legth=result.size();
            
try
            
{
                
// do something with db4o

                
//这里不知道是否是个BUG,我照文档上的用while循环,就outofMemory
                for(int i=0;i<legth;i++)
                
{
                    data.Add(result.next());
//把查询出的对象添加到ArrayList
                }

                
this.grdPeople.DataSource=data;
            
            }

            
finally
            
{
                db.close();
            }


/// <summary>
        
/// 通过简单查询获得数据
        
/// </summary>

        private void ReadDate()
        
{
            ArrayList data
=new ArrayList();

            ObjectContainer db
=Db4o.openFile("formatData.yap");

            
//这里查寻Sex为true的对象
            People people = new People(null,true);//如果对象中的字段为null,那么就匹配所有数据
            
            ObjectSet result 
= db.get(people);
            
int legth=result.size();
            
try
            
{
                
// do something with db4o

                
//这里不知道是否是个BUG,我照文档上的用while循环,就outofMemory
                for(int i=0;i<legth;i++)
                
{
                    data.Add(result.next());
//把查询出的对象添加到ArrayList
                }

                
this.grdPeople.DataSource=data;
            
            }

            
finally
            
{
                db.close();
            }


/// <summary>
        
/// 通过简单查询获得数据
        
/// </summary>

        private void ReadDate()
        
{
            ArrayList data
=new ArrayList();

            ObjectContainer db
=Db4o.openFile("formatData.yap");

            
//这里查寻Sex为true的对象
            People people = new People(null,true);//如果对象中的字段为null,那么就匹配所有数据
            
            ObjectSet result 
= db.get(people);
            
int legth=result.size();
            
try
            
{
                
// do something with db4o

                
//这里不知道是否是个BUG,我照文档上的用while循环,就outofMemory
                for(int i=0;i<legth;i++)
                
{
                    data.Add(result.next());
//把查询出的对象添加到ArrayList
                }

                
this.grdPeople.DataSource=data;
            
            }

            
finally
            
{
                db.close();
            }


4.       对象的高级查询

    /// <summary>
        
/// 高级查询获得数据
        
/// </summary>

        private void SearchDate()
        
{
            ArrayList data
=new ArrayList();

            ObjectContainer db
=Db4o.openFile("formatData.yap");

            Query query 
= db.query();
            query.constrain(
typeof(People));
            
//注意这里的name是类中的字段,属性编译后实际上是两个方法
            query.descend("name").constrain("format").equal();
            ObjectSet result 
= query.execute();
            
int legth=result.size();
            
try
            
{
                
// do something with db4o

                
//这里不知道是否是个BUG,我照文档上的用while循环,就outofMemory
                for(int i=0;i<legth;i++)
                
{
                    data.Add(result.next());
//把查询出的对象添加到ArrayList
                }

                
this.grdPeople.DataSource=data;
            
            }

            
finally
            
{
                db.close();
            }


        }

在db4o中,对象的存储、检索和查询都在对象容器(objectContainer)里完成,它是数据库的一种对象表示。此外,在db4o中,数据的处理是不透明的,因此在处理对象之前,必须明白无误地在数据库中存储和检索对象,这使应用开发过程多了一道步骤。

db4o API提供了一些方法用来控制对象树的读写深度。对于那些对象存放在数据库中的类来说,你不必进行任何特别操作,只要确保类可以串行化即可,不过你必须习惯db4o不同寻常的数据访问方法。

http://sourceforge.net/projects/sodaquery/

    /// <summary>
        
/// 高级查询获得数据
        
/// </summary>

        private void SearchDate()
        
{
            ArrayList data
=new ArrayList();

            ObjectContainer db
=Db4o.openFile("formatData.yap");

            Query query 
= db.query();
            query.constrain(
typeof(People));
            
//注意这里的name是类中的字段,属性编译后实际上是两个方法
            query.descend("name").constrain("format").equal();
            ObjectSet result 
= query.execute();
            
int legth=result.size();
            
try
            
{
                
// do something with db4o

                
//这里不知道是否是个BUG,我照文档上的用while循环,就outofMemory
                for(int i=0;i<legth;i++)
                
{
                    data.Add(result.next());
//把查询出的对象添加到ArrayList
                }

                
this.grdPeople.DataSource=data;
            
            }

            
finally
            
{
                db.close();
            }


        }

在db4o中,对象的存储、检索和查询都在对象容器(objectContainer)里完成,它是数据库的一种对象表示。此外,在db4o中,数据的处理是不透明的,因此在处理对象之前,必须明白无误地在数据库中存储和检索对象,这使应用开发过程多了一道步骤。

db4o API提供了一些方法用来控制对象树的读写深度。对于那些对象存放在数据库中的类来说,你不必进行任何特别操作,只要确保类可以串行化即可,不过你必须习惯db4o不同寻常的数据访问方法。

http://sourceforge.net/projects/sodaquery/

    /// <summary>
        
/// 高级查询获得数据
        
/// </summary>

        private void SearchDate()
        
{
            ArrayList data
=new ArrayList();

            ObjectContainer db
=Db4o.openFile("formatData.yap");

            Query query 
= db.query();
            query.constrain(
typeof(People));
            
//注意这里的name是类中的字段,属性编译后实际上是两个方法
            query.descend("name").constrain("format").equal();
            ObjectSet result 
= query.execute();
            
int legth=result.size();
            
try
            
{
                
// do something with db4o

                
//这里不知道是否是个BUG,我照文档上的用while循环,就outofMemory
                for(int i=0;i<legth;i++)
                
{
                    data.Add(result.next());
//把查询出的对象添加到ArrayList
                }

                
this.grdPeople.DataSource=data;
            
            }

            
finally
            
{
                db.close();
            }


        }

在db4o中,对象的存储、检索和查询都在对象容器(objectContainer)里完成,它是数据库的一种对象表示。此外,在db4o中,数据的处理是不透明的,因此在处理对象之前,必须明白无误地在数据库中存储和检索对象,这使应用开发过程多了一道步骤。

db4o API提供了一些方法用来控制对象树的读写深度。对于那些对象存放在数据库中的类来说,你不必进行任何特别操作,只要确保类可以串行化即可,不过你必须习惯db4o不同寻常的数据访问方法。

http://sourceforge.net/projects/sodaquery/

    /// <summary>
        
/// 高级查询获得数据
        
/// </summary>

        private void SearchDate()
        
{
            ArrayList data
=new ArrayList();

            ObjectContainer db
=Db4o.openFile("formatData.yap");

            Query query 
= db.query();
            query.constrain(
typeof(People));
            
//注意这里的name是类中的字段,属性编译后实际上是两个方法
            query.descend("name").constrain("format").equal();
            ObjectSet result 
= query.execute();
            
int legth=result.size();
            
try
            
{
                
// do something with db4o

                
//这里不知道是否是个BUG,我照文档上的用while循环,就outofMemory
                for(int i=0;i<legth;i++)
                
{
                    data.Add(result.next());
//把查询出的对象添加到ArrayList
                }

                
this.grdPeople.DataSource=data;
            
            }

            
finally
            
{
                db.close();
            }


        }

在db4o中,对象的存储、检索和查询都在对象容器(objectContainer)里完成,它是数据库的一种对象表示。此外,在db4o中,数据的处理是不透明的,因此在处理对象之前,必须明白无误地在数据库中存储和检索对象,这使应用开发过程多了一道步骤。

db4o API提供了一些方法用来控制对象树的读写深度。对于那些对象存放在数据库中的类来说,你不必进行任何特别操作,只要确保类可以串行化即可,不过你必须习惯db4o不同寻常的数据访问方法。

http://sourceforge.net/projects/sodaquery/

    /// <summary>
        
/// 高级查询获得数据
        
/// </summary>

        private void SearchDate()
        
{
            ArrayList data
=new ArrayList();

            ObjectContainer db
=Db4o.openFile("formatData.yap");

            Query query 
= db.query();
            query.constrain(
typeof(People));
            
//注意这里的name是类中的字段,属性编译后实际上是两个方法
            query.descend("name").constrain("format").equal();
            ObjectSet result 
= query.execute();
            
int legth=result.size();
            
try
            
{
                
// do something with db4o

                
//这里不知道是否是个BUG,我照文档上的用while循环,就outofMemory
                for(int i=0;i<legth;i++)
                
{
                    data.Add(result.next());
//把查询出的对象添加到ArrayList
                }

                
this.grdPeople.DataSource=data;
            
            }

            
finally
            
{
                db.close();
            }


        }

在db4o中,对象的存储、检索和查询都在对象容器(objectContainer)里完成,它是数据库的一种对象表示。此外,在db4o中,数据的处理是不透明的,因此在处理对象之前,必须明白无误地在数据库中存储和检索对象,这使应用开发过程多了一道步骤。

db4o API提供了一些方法用来控制对象树的读写深度。对于那些对象存放在数据库中的惯db4o不同寻常的数据访问方法。

http://sourceforge.net/projects/sodaquery/

类来说,你不必进行任何特别操作,只要确保类可以串行化即可,不过你必须习

2005年05月14日

         我们处在软件开发的行业,新的技术日新月异,现在学习不会还是在学结构化的开发,都是使用面向对象的语言了,所以说如何来学习面向对象的软件开发,我们在在众多所谓新技术中如何应对?

         在工作中发现很多同事,在使用c#语言开发,也会说出各种的设计模式,但是查看他的代码,处处留下的是结构化的开发痕迹。有太多的人被淹没在所谓的新技术洪流之中了。为追逐新的工程技术,花了很多的时间在学程序语言层面的语法及应用框架的系统功能与设定,或将 UML 视为是做文件的技术、把面向对象视是一种方法论(methodology)或一种技术。在这样的情况下,往往被迫要选择是学 .NET 或者是 J2EE 的 Solution,因为,要都能精通,似乎是不可能有这样的精力来学习的。

        很多人都忘记了人与生俱有的本性:反思,也就无法去体会软件本质的一面,有空在家多多反思,绝对有好处。从软件的“善变”的角度来看时,抽出来的软件的三个本质:抽象(abstraction)、封装(encapsulation)与接口(interface)。有趣的是,许多软件开发者,会想去学设计模式,但是,光第一个关键,"封装",在系统的设计与开发中却是处处违背。例如,两个应用系统,因数据库是在同一个位置,所以,为了方便及效率的问题,直接读取数据处理,而不是严谨地将数据库确实在逻辑层面分隔开来,透过应用系统的接口来获取数据。我所作的项目,这样的实在是太多了。那么,即使学会许多 "Pattern",却连最基本的原则都无法遵循,又有何用呢?昨天同公司的头聊起相关的话题,ORM/Data Map这些技术公司不敢采用,除非你自己能够完全搞定所有的问题,最后只好还是上个世纪那样写结构化的程序,这里本身就存在问题,采用ORM/Data Map这些技术,就是要求开发者具备良好的面向对象的思想,真正做到使用面向对象的技术去做设计,开发。ORM/Data Map就体现软件的抽象,封装和接口的本质,ORM/Data Map隔离了关系数据库同领域模型的的差异,封装了数据的访问。业务逻辑层通过ORM/Data Map进行数据库访问。把握住最重要的几个本质性(Essential)原则,越少越好,但要更加严谨地遵守及更用心地去观察与体会。会发现实际的程序语言,或应该称之为系统的应用平台(infrastructure)的技术如 .NET and J2EE 等,在本质面几乎是相近的。从本质层面来观察事物,再去印证现实的许多 IT 技术。由内往外,就会发现到,学习的心态与角度会有别于仅从表面看事物,很容易就可以触类旁通。学习及了解所谓的 "新技术" 更是轻而易举了。

2005年04月23日
 版权所有 如有转载请注明出处。
         以我个人的能力,没有足够的时间和资源自行开发一套完整的平台。在已有的众多开源项目中选择若干优秀的项目进行整合。“站在巨人肩膀上”是牛顿有一句名言.,同样适合我们的IT行业。
我对平台的技术架构的构想,是采用开源的ORM框架做数据持久层, Asp.net没有合适的Web层框架,就采用Asp.net的Code-behind方式编写代码,数据持久层同Web表现层之间的连接采用IOC的容器。
1、 开源框架选择:
数据持久层Nhibernate和IbatisNet这两个都是非常优秀的数据持久层,Nhibernate是优秀的Hibernate的dotNet移植版本,在开源社区具有非常高的人气,IbatisNet是Data Mapper框架,也是JAVA版的Ibatis的移植版本,在dotnet的开源社区一样是非常受欢迎的一个工具。Nhibernate用于支持非常好的面向对象的设计的模型,IbatisNet用于支持应用程序的移植(已经存在数据库,处于生产状态),这两个框架对开发人员的要求。这样就具有更大的弹性。IOC容器Spring.Net和Castle,这是两个dotnet非常优秀的IOC容器。Spring.Net同样是Java的Spring 的移植版本,目前的版本是0.6,Castle则是dotnet下出现新的IOC容器,它的功能,成熟度方面比Spring.Net好得多,框架中准备采用Castle.最后的平台的技术架构就是Nhibernate/IbatisNet + Castle + ASP.NET
2、 架构整合:
Web层的Asp.net负责数据输入输出, 响应用户事件,及输入校验的工作,Web层上如何得到Nhibernate的Session和IbatisNet的SqlMapper?本架构中的DAO,Service以及 Nhibernate的Session和IbatisNet的SqlMapper都是通过Castle进行管理,Web层如何得到Castle IOC容器的实例呢,这里采用HttpModule来处理之,使用用HttpContext.Current.Items来保存容器实例,参看http://www.tobinharris.com/nhibernateasp.aspx。Asp.net页面通过Service处理业务逻辑,Service负责use case逻辑, domain相关的逻辑委托给domain model去实现. Service通过DAO完成对domain model的持久化工作. Service负责数据库事务和NHibernate Session/IbatisNet SqlMapper的管理。Domain model负责表示问题域的数据,DAO使用Nhibernate/IbatisNet持久化数据以及查询. 在实现DAO时, 我们使用了Castle的Nhibernate/IbatisNet DAO Support,极大地简化了代码, 很多方法都只用简单的一行完成。这样的架构优点很明显, 层次清晰, 各层的职责也明确, 便于分层设计与开发, 结合mock和Castle的IOC, unit test也是非常容易的. 而且后台(Service, domain model and DAO)的代码不依赖于Asp.net框架,同样的代码可以在Web App也可以在WinForm上面使用,只需更换UI层。
 
使用的框架工具的链接
http://www.castleproject.org/castle/show/HomePage
http://nhibernate.sourceforge.net/
http://sourceforge.net/projects/ibatisnet/
另外这里有一篇精彩文章应用系统架构设计
2005年04月19日

中国“龙芯”系列CPU的主设计师、中科院计算所研究员胡伟武说,“‘龙芯2号’是我国独立自主研究开发的第一个能够在计算机上跑的芯片,我们命名为‘毛泽东110’,这几个字就印在芯片的上面。”他说:“毛主席的革命精神永远不会过时,毛泽东思想永远不会过时。”

  他说,搞科研同样需要井冈山精神。国外大公司Intel、IBM每年投入几十亿美元,上百亿美元研究计算机芯片,中国则少得多。“我们不仅要有‘不怕鬼,不信邪’的精神,还要有‘星星之火,可以燎原’的精神。敢于迎接工作中碰到的种种挑战,对我们年轻人来说非常重要,尤其是在信息产业,我们还比较落后的情况下,更需要有这种精神。”

  胡伟武说,“毛主席在他漫长的革命生涯中,碰到了大量难以想象的困难,但他从来不被困难所吓倒,也不被敌人所吓倒,而是吓倒了一个又一个的敌人,能够做到这一点,不论是他的朋友还是他的敌人都不得不认可。这种精神是在革命中锻炼出来的精神,是我们中华民族五千年来形成的一种精神,我们年轻人就是要学习这种精神,做到战无不胜,攻无不克。在科研中,应当弘扬这种精神。”

  “我很佩服毛主席在复杂情况下总能一下子抓住问题的要害,并且做出正确的战略战术部署。”胡伟武经常对所里的研究生这样说,“工作当中经常会碰到科研和任务这个矛盾,好多博士生强调老让搞型号任务没有时间干科研了,我说这个观点不对,博士生论文必须从任务中来,到任务中去,论文要源于任务,水平要高于任务,而不是为了发表论文而去写论文,我们工科跟理科不大一样。包括我们做CPU研究,要敢于去做,但是方法也很重要,要集中精力打歼灭战,正如毛主席多次强调的,我们在某些面上不如对手,但是在某些点上我们是可以超过的,就要花五六倍的精力,或者三四倍的精力去全力打败对手,通过一些‘点’上的胜利,可以把‘面’带动起来。”

2005年04月16日

处理逻辑(Advice):在某个连接点所采用的处理逻辑。

切点(PointCut):一系列连接点的集合,它指明处理方式(Advice)将在何处被触发,可以使用正则表达式表达。

Advisor:是PointCutAdvice的综合体,完整描述了一个advice将会在pointcut所定义的位置被触发。

附注:

AOP全名Aspect-Oriented Programming,我们先来看看XXX-Oriented的意义,通常翻译「XXX导向」,也就是以XXX为中心,例如中文中「客户导向」就是以客户为中心,而「对象导向」(OOPObject-Oriented Programming)就是以对象为中心的程序设计。
  自然的,Aspect-Oriented Programming,就是「Aspect导向程序设计」,也就是以Aspect为中心的程序设计,但什么是Aspect?中文直译通常是「方面」,但这个名词容易使人混淆。
  牛津字典中的英英解释对Aspect是:particular part or feature of sth being considerd.
  所以Aspect在英文中不只有「方面」的意思,还有部份(part)的意思。中文中称「就这个方面来说」,通常指的是「就这个角度来说」或「就这个方向来说」,这个解释不适用于AOP中的Aspect。如果英文中说from this aspect of sth,除了可以翻译为上面两句的意义之外,还可以翻作「就这个部份来说」。

  以我们的前一个主题中的记录(log)动作插入至HelloSpeaker对象的hello()中为例,我们说「就记录这个部份」是不属于HelloSpeaker职责的,它被硬生生切入HelloSpeaker中,英文中我们可以说:The logging aspect of the "hello" method doesn’t belong to the job of HelloSpeaker.
  所以以整个方法的执行流程来说,如果执行流程是纵向的,则记录这个动作硬生生的「横切」入其中,这个横切入的部份我们就称之为Aspect,它是横切关注点(crosscutting concern,一个concern可以像是权限检查、事务等等)的模块化,将那些散落在对象中各处的程序代码聚集起来。

  所以Aspect要用中文表达的话,适切一些的名词该是「横切面」或「切面」。AOP关注于Aspect,将这些Aspect视作中心进行设计,使其中从职责被混淆的对象中分离出来,除了使原对象的职责更清楚之外,被分离出来的Aspect也可以设计的通用化,可运用于不同的场合。
  来看事务管理这个Aspect如何在动态代理下被抽取出来,下面是一个简单的概念,基本上是在Handler中先激活事务,执行存储层动作,方法执行成功则提交(commit),失败则回滚(rollback):
  代码:

TransactionHandler.java

public class TransactionHandler implements InvocationHandler {

    private Object delegate;

 

    public Object bind(Object obj) {

        this.delegate = obj;

        return Proxy.new ProxyInstance(.., .., ..);

    }

    public Object invoke(Object proxy, Method method, Object[] args) {

        Object result = null;

 

        …..

 

        YourTransaction transaction = null;

        try {

            transaction = yourMethodForGettingTransaction();

 

            result = method.invoke(delegate, args);

 

            transaction.commit();

        }

        catch(YourException e) {

            if(transaction != null) {

                try {

                    transaction.rollback();

                }

                catch(Exception e) {}

            }

        }

 

        ….

 

        return result;

    }

}

  在AOP中,有好几个关键的概念,然而其中更主要的是:PointCutAdviceAdvisor。这些术语并不是很直观,我们配合我们上一个主题的HelloSpeaker来说明会比较容易理解。
  PointCutJointPoint的集合,JointPoint是指Aspect加入的阶段点,例如某个方法被调用,某个成员被存取(Spring不支持),或是某个例外被丢出,以我们前一个主题的HelloSpeaker为例,hello()方法就是一个JointPointPointCutJointPoint的集合,意味着多个方法或例外丢出可以使用同一个处理建议(Advice)。
  Advice是在JointPoint上所要调用的处理建议(在JointPoint上所采取的动作,许多AOP框架通常以interceptor来实作Advice,之后会介绍),例如记录、事务处理、权限检查等。
  Advice类型(advice type)有AroundBeforeThrowsAfter returning。这些Advice类型会分别在以下的时机被调用:在JointPoint前后、JointPoint前、JointPoint丢出例外时、JointPoint执行完毕后。
  就我们上一个例子来说,我们在hello()这个JointPoint上会调用Around Advice,即我们的LogHandler。事务管理调用的Advice类型也是属于Around Advice,即上面的TransactionHandler,调用的JointPoint可能是某个DAO对象的saveXXX()方法。
  AdvisorPointCutAdvice组合在一起,我们前一个主题中的HelloSpeaker例子很简单,故而没有使用到Advisor,之后会介绍到Advisor
  补充:动态代理是比较常见的AOP实作策略,在《Expert One-on-One J2EE Development WIthout EJB Rod JohnsonJuergen Hoeller中的第八章中有提到,AOP的实作有五个主要的策略:

  • Dynamic Proxies

  • Dynamic Byte Code Generation

  • Java Code Generation

  • Use of a Custon Class Loader

Language Extensions

2005年04月06日

http://www.jroller.com/page/hammett/Weblog?catname=%2FCastle

代码生成工具工具NVelocity – A .Net Template Engine

2005年04月03日

Rails是一个open source的使用Ruby开发web应用的框架,它采用了流行的MVC模式,本文介绍了一个简单的基于数据库的web应用的开发。

翻译自 http://www.rubyonrails.org/show/TutorialStepOne
翻译   http://www.ruby-cn.org
原文分六步六页,这里简化到一页。

1 创建数据库

创建名为rails_production的数据库,以及有访问数据库权限的用户。本例数据库如下:
#
#
数据库 : `rails_production`
#

# ——————————————————–

#
#
`people`定义
#

CREATE TABLE `people` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(50) NOT NULL default ”,
  `street1` varchar(70) NOT NULL default ”,
  `street2` varchar(70) NOT NULL default ”,
  `city` varchar(70) NOT NULL default ”,
  `state` char(2) NOT NULL default ”,
  `zip` varchar(10) NOT NULL default ”,
  PRIMARY KEY  (`id`),
  KEY `name` (`name`)
) TYPE=MyISAM AUTO_INCREMENT=2 ;

#
#
`people`插入数据
#

INSERT INTO `people` VALUES (1, ‘Superman’, ‘123 Somewhere’, ”, ‘Smallville’, ‘KS’, ‘123456′);


2
.设置数据库参数
编辑config/database.yml(明天我做个东西配置文件教*.zml了:-)),相应的例子如下:

My Sql
production:
  adapter: mysql
  database: rails_production
  host: localhost
  username: root
  password:
SQLite
production:
  adapter: sqlite
  dbfile: ../db/rails-production.db

test:
  adapter: sqlite
  dbfile: ../db/rails-test.db
Postgre SQL
production:
  adapter: postgresql
  database: rails_production
  username: postgres
  password:

test:
  adapter: postgresql
  database: rails_test
  username: postgres
  password:


3
.创建控制器
如果还没有创建rails应用,先要创建它。如:
rails path/to/your/new/railsapp
【注意】这将删除这个目录下的已有的rails应用。
创建新的控制器用new_controller(查看文档可以不带参数运行它)。本例如下:
./script/new_controller Friends list display new edit
: new_controller new_model(下面会看到)命令都需要包括ruby路径设置的一行,如果需要改变这些参数,可以丛script文件夹打开这些文件直接修改,设置ruby的正确位置。
: 不要定义任何叫做‘process’action, 这个方法是系统正确工作必须得,你不能重载它。
: Windows用户需要这样来运行程序。
ruby script/new_controller Friends list display new edit

4.创建模型model
创建模型用命令script/new_model,同样,不带参数可以查看本命令的帮助文档。
./script/new_model Person
5
.然后进入rails目录,如果安装了rake程序的话,运行 “rake”。这将测试你的rails应用是否正确部署了。
: 在版本0.5.0中,这个测试只支持mysql,所以如果你用sqlite或者psql出错的话,不必担心。

6.开发rails应用
打开views/friends/display.rhtml文件,当然在rails应用目录下。这个文件是前几步自动产生的,需要我们往里面填充一些东西。修改后如下:

<html>
<body>
<h1>Friends#display</h1>
This page should display one friend
<p />
<%= @person.name %><br/>
<%= @person.city %><br/>

</body>
</html>

这里面有一些动态内容,其中@person对象需要控制器来创建,所以打开controllers/friends_contrller.rb。一些方法已经被自动创建了,但是model还没有被连接进来,所以在require顶部加入:
require ‘person’
这将引入我们定义好的 Active Record 类,通过它我们就可以访问数据库了。
找到名为display的方法,改成下面的:
def display
  @person = Person.find(1)
end


这将从数据库中选出第一个记录,并放入@person变量,供view使用。
现在,我们再来看看model类,打开models/person.rb文件。同样系统已经为我门做了很多工作,已经为我们创建了访问属性的方法,所以不需要我们再写了。需要做的事情是这个类如何映射的我们创建的数据库表。Active Record负责了对象名到表名的映射。具体参见:http://api.rubyonrails.org/classes/ActiveRecord/Base.html

现在我们要做的只是把这个方法加入到Person:
def self.table_name()
“people”
end
然后打开浏览器,打开地址http://rails/friends/display
 ”rails”
是机器名,如果一切正常,你应该能看到应用已经开始工作了。
注意URL中包括控制器friendsaction display

Rails’ web site http://www.rubyonrails.org/show/HomePage

Dotnet平台上使用Rails的请关注Castle On rails项目哦,可以通过此处察看:

http://www.castleproject.org/castle/show/castleonrails

只不过需要拥有服务器的控制权限,他的后缀名称是rails,要配置IIS以便支持此文件名,目前可以支持ashx,但普通的虚拟主机依然无法使用,这可能是个比较麻烦的地方.这里有很多Rail的东西http://blog.csdn.net/ruby_cn/category/65002.aspx

http://blog.itpub.net/category/325/821

 

可以查看此地址

http://www.castleproject.org/castle/show/ActiveRecord

使用此工具可以免去编写NHibernate的配置文件,完全在代码内使用属性配置就可以自动内部映射成NHibernate所需要的数据库映射文件.上面有具体的例子,感兴趣就去瞧瞧

http://rubyforge.org/projects/activerecord/

2005年03月22日

 

1。下载:
http://www.postgresql.org/download/
我是选择的http://ftp.isu.edu.tw/pub/Unix/Database/PostgreSQL/binary/v8.0.1
然后在这里下载win32目录下的文件
http://ftp.isu.edu.tw/pub/Unix/Database/PostgreSQL/binary/v8.0.1/win32/postgresql-8.0.1.zip
2.解压后运行postgresql-8.0.msi.
一路上基本使用默认值即可,但是postgresql安装的位置所在的盘必须是NTFS格式的。
如果要安装成系统服务的话,需要选择或者创建一个用来启动服务的本地用户。
进行到下面的安装画面时,画红圈的地方是需要选择成如图的样子的:
copyright @ lizongbo
 

copyright @ lizongbo

会得到下面的提示:
 
3.安装结束后,开始设置pg_hba.conf。
开始菜单–>程序–>Postgresql 8.0–>Configuration files–>Edit pg_hba.conf。
修改为如下内容:
# IPv4 local connections:
host    all         all         127.0.0.1/32          trust
host    all         all         192.168.9.226/32      trust
这样表示本机和192.168.9.226这台机器连接数据库的时候,永远信任而且不需要用户名和密码。
这样在开发和调试及部署的时候将非常方便。
 
4.在计算机管理的服务里重新启动postgresql.

copyright @ lizongbo

copyright @ lizongbo
5.数据库管理。

copyright @ lizongbo

开始菜单–>程序–>Postgresql 8.0–>pgAdmin III。
也可以使用EMS PostgreSQL Manager (必须2.7以上版本才支持postgresql8.0,现在版本是2.8)进行管理。

2005年03月18日

JIRA可真是个好东西啊,自定义能力超强,虽然主要是用来做bug跟踪管理的,但是很容易的就可以改造成项目管理系统.只可惜是要收费的,为了使用它,sorry啊,只好下载了一个注册机.不过下载的注册机是JIRA3.0版的,现在的JIRA已经出到3.1版了.试了一下发现注册机不行用.几乎放弃了就,但是仔细分析了一下JIRA的包的结构,发现注册机不行用很可能是因为3.1版的包结构改变了,破解需要的那个licence包的位置变掉了.于是抱着侥幸心理把下载的注册机keygen.class反编译了一下,结果发现注册机没有被混淆过,很容易就看到了所有的代码,于是就将注册机import的包名改了一下,重新编译,呃,可以用了,真是对不起,做了错事了.

 // Decompiled by DJ v3.7.7.81 Copyright 2004 Atanas Neshkov  Date: 2005-2-26 22:13:16
// Home Page :
http://members.fortunecity.com/neshkov/dj.html  – Check often for new version!
// Decompiler options: packimports(3)
// Source File Name:   keygen.java

import com.atlassian.License.LicensePair;
import java.io.*;
import java.security.KeyFactory;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;

public class keygen
{

    public keygen()
    {
    }

    public static void main(String args[])
        throws IOException
    {
        try
        {
            long l = 267L;
            long l1 = System.currentTimeMillis();
            long l2 = System.currentTimeMillis();
            String s = “”;
            System.out.println(“Keygen for JIRA Enterprise Edition.”);
            System.out.print(“created by mydaj[ROR].”);
            do
            {
                System.out.print(“\nEnter your organization name: “);
                for(int i = System.in.read(); i != 10 && i != 13; i = System.in.read())
                    s = s + (char)i;

            } while(s == “”);
            try
            {
                PKCS8EncodedKeySpec pkcs8encodedkeyspec = new PKCS8EncodedKeySpec(EncodedPrvKey);
                KeyFactory keyfactory = KeyFactory.getInstance(“DSA”, “SUN”);
                java.security.PrivateKey privatekey = keyfactory.generatePrivate(pkcs8encodedkeyspec);
                String s1 = Long.toString(l, 10);
                s1 = s1 + “^^”;
                s1 = s1 + Long.toString(l1, 10);
                s1 = s1 + “^^”;
                s1 = s1 + Long.toString(l2, 10);
                s1 = s1 + “^^”;
                s1 = s1 + s;
                byte abyte0[] = s1.getBytes();
                Signature signature = Signature.getInstance(“SHA1withDSA”);
                signature.initSign(privatekey);
                signature.update(abyte0);
                byte abyte1[] = signature.sign();
                LicensePair licensepair = null;
                try
                {
                    licensepair = new LicensePair(abyte0, abyte1);
                }
                catch(Exception exception1)
                {
                    exception1.printStackTrace();
                }
                System.out.println(s1);
                System.out.println(“Your license key is: “);
                System.out.println(licensepair.toString());
            }
            catch(Exception exception)
            {
                exception.printStackTrace();
            }
        }
        catch(IOException ioexception) { }
    }

    static byte EncodedPrvKey[] = {
        48, -126, 1, 75, 2, 1, 0, 48, -126, 1,
        44, 6, 7, 42, -122, 72, -50, 56, 4, 1,
        48, -126, 1, 31, 2, -127, -127, 0, -3, 127,
        83, -127, 29, 117, 18, 41, 82, -33, 74, -100,
        46, -20, -28, -25, -10, 17, -73, 82, 60, -17,
        68, 0, -61, 30, 63, -128, -74, 81, 38, 105,
        69, 93, 64, 34, 81, -5, 89, 61, -115, 88,
        -6, -65, -59, -11, -70, 48, -10, -53, -101, 85,
        108, -41, -127, 59, -128, 29, 52, 111, -14, 102,
        96, -73, 107, -103, 80, -91, -92, -97, -97, -24,
        4, 123, 16, 34, -62, 79, -69, -87, -41, -2,
        -73, -58, 27, -8, 59, 87, -25, -58, -88, -90,
        21, 15, 4, -5, -125, -10, -45, -59, 30, -61,
        2, 53, 84, 19, 90, 22, -111, 50, -10, 117,
        -13, -82, 43, 97, -41, 42, -17, -14, 34, 3,
        25, -99, -47, 72, 1, -57, 2, 21, 0, -105,
        96, 80, -113, 21, 35, 11, -52, -78, -110, -71,
        -126, -94, -21, -124, 11, -16, 88, 28, -11, 2,
        -127, -127, 0, -9, -31, -96, -123, -42, -101, 61,
        -34, -53, -68, -85, 92, 54, -72, 87, -71, 121,
        -108, -81, -69, -6, 58, -22, -126, -7, 87, 76,
        11, 61, 7, -126, 103, 81, 89, 87, -114, -70,
        -44, 89, 79, -26, 113, 7, 16, -127, -128, -76,
        73, 22, 113, 35, -24, 76, 40, 22, 19, -73,
        -49, 9, 50, -116, -56, -90, -31, 60, 22, 122,
        -117, 84, 124, -115, 40, -32, -93, -82, 30, 43,
        -77, -90, 117, -111, 110, -93, 127, 11, -6, 33,
        53, 98, -15, -5, 98, 122, 1, 36, 59, -52,
        -92, -15, -66, -88, 81, -112, -119, -88, -125, -33,
        -31, 90, -27, -97, 6, -110, -117, 102, 94, -128,
        123, 85, 37, 100, 1, 76, 59, -2, -49, 73,
        42, 4, 22, 2, 20, 42, 50, -88, 30, 125,
        -37, 118, -50, 20, -82, -63, 0, 8, -36, 106,
        -9, -110, 124, 107, 68
    };

}