??xml version="1.0" encoding="utf-8" standalone="yes"?> 许多q以来,对于软g目Q企业Y件开发的L实践一直都們于在单一的通用~程语言上进行标准化Q从而得Java和C#成ؓ今天~程语言的主选择。随着来多的目光开始投向DSLQ也许我们的前脚已经t在了一道新的门槛之上,向前望去Q我们会发现在Y仉目中采用多种语言已经成ؓ一个标准,?0q代?0q代初出现的问题不会重现?/p> Martin Fowler提出Q也许我们正在迈q这L一个新时期Q?/p> FowlerUͼ“像Hibernate、Struts和ADOq样的大型框Ӟlh们在学习上带来的挑战Q绝不亚于学习一门语aQ即便你在单一一门宿主语a上用这些框架编E也是如此?#8221;此外Q在它们的宿主语a中表q需求的隑ֺ可能会相当大Qƈ可能引出W拙隄的配|文Ӟ“q些配置文g实际上就是用XML写的外部领域特定语言”?/p> 在语a中嵌入DSLQ而不是用类库,可能会是一个更为合适的解决Ҏ。Martinl出了这L一个分析结论:“API好比是在声明一个词汇表Q而DSL则ؓ其增加了相应的语法,使得Z能够写出条理清晰的句子?#8221;因此Q用DSL而不是框架会使代码丰富表现力QؓZ带来“更良好的抽象处理方式”Qƈ?#8220;阅读我们写出的代码及Ҏ们意囄展示变得更加Ҏ”?/p> Piers CawleyU?/a>QDSL的主要特性ƈ非其可读性,而是“它们对去相应领域的高度专?#8221;使得它们能够更加明确地表义。CawleyZ阐述他的观点举了一个例子,说明DSL不仅仅能让我?#8220;写出读v来像领域专家说出来的话一LE序”Q也可以很技术化Q用来代表一个用它们的语法q行操控的框架?/p> Neal Ford也相信,被他UCؓ多语a~程QPolyglot ProgrammingQ的势头正在兴v。在软g开发的q个新纪元中Q日益明昄主要特征是嵌入更多的语aQZ能够“为所做的菜选择一把恰到好处的刀Qƈ且恰如其分地使用?#8221;。他举了一个例子,展示在Java~程语言中ƈ行类库的使用隑ֺQƈ其与Haskell作比。Haskell是一门函数式语言Q?#8220;消除了变量所带来的副作用”Qƈ?#8220;~写U程安全的代?#8221;变得更容易。Ford_Java?NETq_都存在Haskell语言的实玎ͼJaskell和Haskell.netQ?/p> 不再使用单一语言q行开发所带来的风险之一可能?0q代?0q代初所出现的问题又再次重现Q当时语a是完全独立的^収ͼ既不能互操作也不能放在一赯好地使用。Martin Fowler指出Q现在的情况有这L一个重要区别: 最l,要学习ƈ使用多种语言Q对于业界乃臛_发h员都可能会变成一w要资产。《Pragmatic Programmers》这本书里面p刎ͼ׃q样做会对h们对~程的思考方式生媄响,因此q样能帮助h们发现解决问题的新途径?/p> 您是怎样认ؓ的呢Q在下去的五q中Q我们会开始合用语aQƈ像用cd一样频J地使用DSL吗? AspectJ是一个面向切面的框架Q它扩展了Java语言。AspectJ定义?a target="_new">AOP语法所以它有一个专门的~译器用来生成遵守Java字节~码规范?a target="_new">Class文g?/font> ? QFigureEditor例子?a target="_new">UML?/p>
AspectJQ也是AOPQ的动机是发现那些用传l的~程Ҏ无法很好处理的问题。考虑一个要在某些应用中实施安全{略的问题。安全性是贯穿于系l所有模块间的问题,每个模块都需要应用安全机制才能保证整个系l的安全性,很明显这里的安全{略的实施问题就是一个横切关注点Q用传l的~程解决此问题非常的困难而且Ҏ产生差错Q这正是AOP发挥作用的时候了?/p>
传统?a target="_new">面向对象~程中,每个单元是一?a target="_new">c?/a>Q而类g安全性这斚w的问题,它们通常不能集中在一个类中处理因为它们横跨多个类Q这导致了代码无法重用Q可l护性差而且产生了大量代码冗余,q是我们不愿意看到的?/p>
面向斚w~程的出现正好给处于黑暗中的我们带来了光明,它针对于q些横切x点进行处理,好?a target="_new">面向对象~程处理一般的x点一栗而作为AOP的具体实C一的AspectJQ它向Java中加入了q接点(Join PointQ这个新概念Q其实它也只是现存的一个Java概念的名U而已。它向Java语言中加入少许新l构Q切?pointcut)、通知(Advice)?a target="_new">cd间声?Inter-type declaration)和方?Aspect)。切点和通知动态地影响E序程Q类型间声明则是静态的影响E序的类{l构Q而方面则是对所有这些新l构的封装?/p>
一个连接点是程序流中指定的一炏V切Ҏ集特定的q接炚w合和在这些点中的倹{一个通知是当一个连接点到达时执行的代码Q这些都是AspectJ的动态部分。其实连接点好比是E序中的一条一条的语句Q而切点就是特定一条语句处讄的一个断点,它收集了断点处程序栈的信息,而通知是在这个断点前后想要加入的E序代码。AspectJ中也有许多不同种cȝcd间声明,q就允许E序员修改程序的静态结构、名U、类的成员以及类之间的关pRAspectJ中的斚w是横切关注点的模块单元。它们的行ؓ与Java语言中的cd象,但是斚wq封装了切点、通知以及cd间声明?/p>
动态连接点模型 M面向斚w~程的关键元素就是连接点模型。AspectJ提供了许多种cȝq接炚w合,但是本篇只介l它们中的一个:Ҏ调用q接炚w(method call join points)。一个方法调用连接点捕捉对象的方法调用。每一个运行时Ҏ调用都是一个不同的q接点,许多其他的连接点集合可能在方法调用连接点执行时运Q包括方法执行时的所有连接点集合以及在方法中其他Ҏ的调用。我们说q些q接炚w合在原来调用的连接点的动态环境中执行?/p>
切点 在AspectJ中,切点捕捉E序中特定的连接点集合。例如,切点 call(void Point.setX(int)) 捕捉每一个签名ؓvoid Point.setX(int)的方法调用的q接点,也就是说Q调用Point对象的有一个整型参数的void setXҎ。切点能与其他切炚w过?||)、与(&&)以及?!)操作W联合。例?call(void Point.setX(int)) || call(void Point.setY(int)) 捕捉setX或setY调用的连接点。切点还可以捕捉不同cd的连接点集合Q换句话_它们能横切类型。例?/p>
call(void FigureElement.setXY(int,int)) || call(void Point.setX(int)) || call(void Point.setY(int) || call(void Line.setP1(Point)) || call(void Line.setP2(Point)); 捕捉上述五个Ҏ调用的Q意一个的q接炚w合。它在本文的例子中捕捉当FigureElementUd时的所有连接点集合。AspectJ使程序员可以命名一个切炚w合,以便通知的用。例如可以ؓ上面的那些切点命?/p>
pointcut move(): call(void FigureElement.setXY(int,int)) || call(void Point.setX(int)) || call(void Point.setY(int)) || call(void Line.setP1(Point)) || call(void Line.setP2(Point)); 无论什么时候,E序员都可以使用move()代替捕捉q些复杂的切炏V?/p>
前面所说的切点都是Z昄的方法签名,它们UCؓZ名字(name-based)横切。AspectJq提供了另一U横切,UCؓZ属?property-based)的横切。它们可以用通配W描q方法签名,例如 call(void Figure.make*(..)) 捕捉Figure对象中以make开头的参数列表L的方法调用的q接炏V?call(public & Figure.*(..)) 则捕捉Figure对象中的M公共Ҏ调用的连接点。但是通配W不是AspectJ支持的唯一属性,AspectJ中还有许多其他的属性可供程序员使用。例如cflowQ它Ҏq接炚w合是否在其他q接炚w合的动态环境中发生标识q接炚w合。例?cflow(move()) 捕捉被move()捕捉到的q接炚w合的动态环境中发生的连接点?/p>
通知 虽然切点用来捕捉q接炚w合,但是它们没有做Q何事。要真正实现横切行ؓQ我们需要用通知机制。通知包含了切点和要在每个q连接点处执行的代码DcAspectJ有几U通知?/p>
·前通知(Before Advice) 当到达一个连接点但是在程序进E运行之前执行。例如,前通知在方法实际调用之前运行,刚刚在方法的参数被分析之后?/p>
Before() : move(){ System.out.println(“物体移动了”);} ·后通知(After Advice) 当特定连接点处的E序q程执行之后q行。例如,一个方法调用的后通知在方法体q行之后Q刚好在控制q回调用者之前执行。因为JavaE序有两U退接点的Ş式,正常的和抛出异常。相对的有三种后通知Q返回后通知(after returning)、抛出异常后通知(after throwing)和清楚的后通知(after)Q所谓清楚后通知是指无论是正常q是异常都执行的后通知Q就像Java中的finally语句?/p>
After() returning : move(){ System.out.println(“物体刚刚成功的移动了”);} ·在周围通知(Around Advice) 在连接点到达后,昄的控制程序进E是否执行(暂不讨论Q?/p>
暴露切点环境 切点不仅仅捕捉连接点Q它q能暴露q接点处的部分执行环境。切点中暴露的值可以在通知体中声明以后使用。通知声明有一个参数列表(和方法相同)用来描述它所使用的环境的名称。例如后通知 after(FigureElement fe,int x,int y) returning : somePointcuts { someCodes } 使用了三个暴露的环境Q一个名为fe的FigureElement对象Q两个整型变量x,y。通知体可以像使用Ҏ的参数那样用这些变量,例如 after(FigureElement fe,int x,int y) returning : somePointcuts { System.out.println(fe+”Ud?”+x+”,”+y+”)”); } 通知的切点发布了通知参数的|三个原生切点this、target和args被用来发布这些?所以上qC子的完整代码?/p>
after(FigureElement fe,int x,int y) returning : call(void FigureElement.setXY(int,int) && target(fe) && args(x,y) { System.out.println(fe+”Ud?”+x+”,”+y+”)”); } 目标对象是FigureElement所以fe是after的第一个参敎ͼ调用的方法包含两个整型参数所以x和y为after的第二和W三个参数。所以通知打印出方法setXY调用q回后对象移动到的点x和y。当然还可以使用命名切点完成同样的工作,例如 pointcut setXY(FigureElement fe,int x,int y):call(void FigureElement.setXY(int,int) && target(fe) && args(x,y); after(FigureElement fe,int x,int y) returning : setXY(fe,x,y){ System.out.println(fe+”Ud?”+x+”,”+y+”)”); } cd间声?/p>
AspectJ的类型间声明指的是那些跨类和它们的{l构的声明。这些可能是横跨多个cȝ成员声明或者是cM间承关pȝ改变。不像通知是动态地操作Q类型间声明~译时的静态操作。考虑一下,Java语言中如何向一个一些的cM加入新方法,q需要实C个特定接口,所有类都必d各自内部实现接口声明的方法,而用AspectJ则可以将q些工作利用cd间声明放在一个方面中。这个方面声明方法和字段Q然后将它们与需要的c联pR?/p>
假设我们x一个Sreen对象观察Point对象的变化,当Point是一个存在的cR我们可以通过书写一个方面,p个方面声明Point对象有一个实例字Dobservers,用来保存所有观察Point对象的Screen对象的引用,从而实现这个功能?/p>
Aspect PointObserving{ Private Collection Point.observers=new ArrayList(); …… } observers字段是私有字D,只有PointObserving能用。因此,要在aspect中加入方法管理observers聚集?/p>
Aspect PointObserving{ Private Collection Point.observers=new ArrayList(); Public static void addObserver(Point p,Screen s){ p.observers.add(s); } public static void removeObserver(Point p,Screen s){ p.observers.remove(s); } …… } 然后我们可以定义一个切点stateChanges军_我们惌观察什么ƈ且提供一个after通知定义当观察到变化时我们想要做什么?/p>
Aspect PointObserving{ Private Collection Point.observers=new ArrayList(); Public static void addObserver(Point p,Screen s){ p.observers.add(s); } public static void removeObserver(Point p,Screen s){ p.observers.remove(s); } pointcut stateChanges(Point p) : target(p) && call(void Point.set*(int)); after(Point p) : stateChanges(p){ Iterator it=p.observers.iterator(); While(it.hasNext()){ UpdateObserver(p,(Screen)it.next())); } } private static void updateObserver(Point p,Screen s){ s.display(p); } } 注意无论是Sreenq是Point的代码都没有被修改,所有的新功能的加入都在斚w中实CQ很酷吧Q?/p>
斚w 斚w以横切模块单元的形式包装了所有的切点、通知和类型间声明。这非常像Java语言的类。实际上Q方面也可以定义自己的方法,字段和初始化Ҏ。像cM样一个方面也可以用abstrace关键字声明ؓ抽象斚wQ可以被子方面ѝ在AspectJ中方面的设计实际上用了单例模式Q缺省情况下Q它不能使用new构造,但是可以使用一个方法实例化例如ҎaspectOf()可以获得斚w的实例。所以在斚w的通知中可以用非静态的成员字段?/p>
例如 aspect Tracing { OutputStream trace=System.out; After() : move(){ trace.println(“物体成功Ud”); } 如前所qͼAspectJ可以用于应用开发的不同阶段。下面讨Z同阶D늚AspectJ的具体应用情c?/p>
开发型斚w(Development Aspects) 开发方面可以很Ҏ的从真正的品中删除。而品方面则被可用于开发过E和生q程Q但是仅仅媄响某几个cR?/p>
q一部分通过几个例子说明斚w在Java应用的开发阶D|如何使用的。这些方面包括调试、测试和性能等工作。方面定义的行ؓ范围包括单的代码跟踪、测试应用的内在联系{等。用AspectJ不仅使得模块化这些功能变为可能,同时也得根据需要打开和关闭这些功能变成可能?/p>
代码跟踪(Tracing) aspect SimpleTracing { Entering: call(void FigureElement.draw(GraphicsContext)) 通常我们在调式程序时Q会在特定的地方攄几条输出语句Q而当调试l束时还需要找到这些代码段它们删除,q样做不但我们的代码很隄而且很费旉。而用AspectJ我们可以克服以上的两个问题,我们可以通过定义切点捕捉M惌观察的代码段Q利用通知可以在方面内部书写输句,而不需要修Ҏ代码Q当不在需要跟t语句的时候还可以很轻杄方面从应用中删除ƈ重新~译代码卛_?/p>
前提条g和后l条?Pre-and Post-Conditions) aspect PointBoundsChecking { pointcut setX(int x): (call(void FigureElement.setXY(int, int)) && args(x, *)) || (call(void Point.setX(int)) && args(x)); pointcut setY(int y): (call(void FigureElement.setXY(int, int)) && args(*, y)) || (call(void Point.setY(int)) && args(y)); before(int x): setX(x) { if ( x < MIN_X || x > MAX_X ) throw new IllegalArgumentException("x is out of bounds."); } before(int y): setY(y) { if ( y < MIN_Y || y > MAX_Y ) throw new IllegalArgumentException("y is out of bounds."); } } 它实C边界功能。当FigureElement对象UdӞ如果x或y的Dq了定义的边界,E序会抛出IllegalArgumentException异常?/p>
合同实施(Contract Enforcement) static aspect RegistrationProtection { pointcut register(): call(void Registry.register(FigureElement)); pointcut canRegister(): withincode(static * FigureElement.make*(..)); before(): register() && !canRegister() { throw new IllegalAccessException("Illegal call " + thisJoinPoint); } } q个斚w使用了withincode初始切点Q它表示在FigureElement对象的工厂方?以make开始的Ҏ)体内出现的所有连接点。在before通知中声明一个异常,该通知用于捕捉M不在工厂Ҏ代码内部产生的registerҎ的调用。该通知在特定连接点处抛Z个运行时异常Q但是AspectJ能做地更好。用declare error的Ş式,我们可以声明一个编译时的错误?/p>
static aspect RegistrationProtection { pointcut register(): call(void Registry.register(FigureElement)); pointcut canRegister(): withincode(static * FigureElement.make*(..)); declare error: register() && !canRegister(): "Illegal call" } 当用这个方面后Q如果代码中存在定义的这些非法调用我们将无法通过~译。这U情况只出现在我们只需要静态信息的时候,如果我们需要动态信息,像上面提到的前提条g实施Ӟ可以利用在通知中抛出带参数的异常来实现?/p>
配置理(Configuration Management) 产品型方?Production Aspects) q一部分的方面例子将描述斚w用于生阶段的应用。品方面将向应用中加入功能而不仅仅为程序的内部工作增加可视性?/p>
改变监视(Change Monitoring) aspect MoveTracking { private static boolean dirty = false; public static boolean testAndClear() { boolean result = dirty; dirty = false; return result; } pointcut move(): call(void FigureElement.setXY(int, int)) || call(void Line.setP1(Point)) || call(void Line.setP2(Point)) || call(void Point.setX(int)) || call(void Point.setY(int)); after() returning: move() { dirty = true; } } q个单例子同栯明了在品代码中使用AspectJ的一些好处。考虑使用普通的Java代码实现q个功能Q将有可能需要包含标志位QtestAndClear以及setFlagҎ的辅助类。这些方法需要每个移动的囑Ş元素包含一个对setFlagҎ的调用。这些方法的调用是q个例子中的横切x炏V?/p>
·昄的捕捉了横切x点的l构 ·功能Ҏ拔插 ·实现更加E_ 传递上下文(Context Passing) 使用AspectJQ这U上下文的传递可以用模块化的方式实现。下面代码中的after通知仅当一个图形对象的工厂Ҏ在客户ColorControllingClient的某个方法控制流E中调用时才q行?/p>
aspect ColorControl { pointcut CCClientCflow(ColorControllingClient client): cflow(call(* * (..)) && target(client)); pointcut make(): call(FigureElement Figure.make*(..)); after (ColorControllingClient c) returning (FigureElement fe): make() && CCClientCflow(c) { fe.setColor(c.colorFor(fe)); } } q个斚w仅仅影响一部分的ҎQ但是注意该功能的非AOP实现可能 需要编辑更多的Ҏ?/p>
提供一致的行ؓ(Providing Consistent Behavior) aspect PublicErrorLogging { Log log = new Log(); pointcut publicMethodCall(): call(public * com.bigboxco.*.*(..)); after() throwing (Error e): publicMethodCall() { log.write(e); } } 在一些情况中Q这个方面可以记录一个异怸ơ。这在com.bigboxco包内部的代码自己调用本包中的公共Ҏ时发生。ؓ解决q个问题Q我们可以用cflow初始切点这些内部调用排除: after() throwing (Error e) : publicMethodCall() && !cflow(publicMethodCall()) { log.write(e); } l论 AspectJ是对Java语言的简单而且实际的面向方面的扩展。仅通过加入几个新结构,AspectJ提供了对模块化实现各U横切关注点的有力支持。向以有的Java开发项目中加入AspectJ是一个直接而且渐增的Q务。一条\径就是通过从用开发方面开始再C品方面当拥有了AspectJ的经验后׃用开发可重用斚w。当然可以选取其他的开发\径。例如,一些开发者将从用品方面马上得到好处,另外的h员可能马上编写可重用的方面?/p>
AspectJ可以使用Z名字和基于属性这两种横切炏V用基于名字横切点的方面仅影响数几个c,虽然它们是小范围的,但是比v普通的Java实现来说它们能够减少大量的复杂度。用基于属性横切点的方面可以有范围或着大范围。用AspectJD了横切关注点的干净、模块化的实现。当~写AspectJ斚wӞ横切x点的l构变得十分明显和易懂。方面也是高度模块化的,使得开发可拔插的横切功能变成现实?/p>
AspectJ提供了比q两部分短介l更多的功能。本pd的下一章内容,The AspectJ LanguageQ将介绍 AspectJ语言的更多细节和特征。系列的W三章,Examples通过一些完整的例子说明如何使用AspectJ。徏议大家在仔细阅读了接下来的两章后再决定是否在目中加入AspectJ?/p>
Q一Q、The reflection API 说到高Ҏ,首先要说的就是AspectJ提供的一套reflection APIQ主要包括JoinPoint、JoinPoint.StaticPart和Signature三个主要的接口。你可以从aspectj.jar中的javadoc来了解它们的详细情况。那它们能提供什么功能呢Q其实从字面上就能大致明白:通过q三个接口能讉K到Join Points的信息。譬如,调用thisJoinPoint.getArgs()可以得到方法的参数列表?/p>
Q二Q、Aspect precedence 在AspectJ中,pointcut和advice都会包含在一个aspect中。在应用pȝ中,对同一个join point会有多种adviceQloggingQcaching{)Q这׃引出一个问题:如果pȝ中有很多的aspectQ而这些aspect很有可能会捕获同Ljoin pointsQ那q些aspect的执行顺序是如何安排的呢Q?/p>
AspectJ早已为我们考虑Cq个问题Q它提供了一U设|aspect precedence的方法。对三种不同的advice来说Q?/p>
1、before advice是先执行higher-precedenceQ后执行lower-precedenceQ?/p>
2、around advice是higher-precedence包含lower-precedenceQ当higher-precedence around advice没有调用proceed()ҎӞlower-precedence不会被执行; 3、after advice与before advice正好相反Q先执行执行lower-precedenceQ然后执行higher-precedence?/p>
那应该如何来声明aspect precedenceQ非常简单,只要在aspect中用如下的语法卛_Q?/p>
declare precedence : TypePattern1, TypePattern2, ..; 从左往叻I排在前面的是higher-precedence adviceQ后面的是lower-precedence?/p>
Q三Q、Aspect association 在Java中,Z节省对象每次构徏的耗费Q增加效率,很多Z考虑使用Singleton模式Q让jvm中只有一个实例存在。AspectJ当然为我们考虑到这个问题,Aspect association实际上就是aspect与advised join point object的一U关联关p,q很cM?a target="_new">OO 在AspectJ中可以把Aspect association大致分ؓ三类Q?/p>
1、Per virtual machine (default) 一个jvm中只有一个aspect instanceQAspectJ默认association?/p>
2、Per object 每一个advised join point object都会产生一个aspect instanceQ不q同一个object instance只会产生一个aspect instance?/p>
3、Per control-flow association q种associationE微复杂一些,它主要针对程序调用的控制,譬如QAҎ调用BҎQBҎ又调用CҎQ这是control-flow?/p>
在aspect中声明这三种association非常单,它的主要语法如下Q?/p>
aspect [(
Per virtual machine是aspectj的默认associationQ不需要你额外的声明,正常使用卛_?/p>
Per object主要有两U方式:perthis()和pertarget()。perthis()主要用于execution objectQpertarget()主要用于target objectQ两者非常类伹{?/p>
Per control-flow中也包含两种方式Qpercflow()和percflowbelow()。这两者也很类|只是两者的control-flow不太一栯已?/p>
l护aspect的状态信息还有一U方法,是使用introduce。可以在aspect中introduce member fieldsQ通过fields来保存状态信息?/p>
四、AspectJ实例 使用斚w的TracingE序 写一个具有跟t能力的cL很简单的事情Q一l方法,一个控制其开或关的布变量,一U可选的输出,可能q有一些格式化输出能力。这些都是Tracec需要的东西。当Ӟ如果E序需要的话,TracecM可以实现的十分的复杂。开发这LE序只是一斚wQ更重要的是如何在合适的时候调用它。在大型pȝ开发过E中Q跟t程序往往影响效率Q而且在正式版本中去除q些功能十分ȝQ需要修改Q何包含跟t代码的源码。出于这些原因,开发h员常怋用脚本程序以便向源码中添加或删除跟踪代码?/p>
AspectJ可以更加方便的实现跟t功能ƈ克服q些~点。Tracing可以看作是面向整个系l的x点,因此QTracing斚w可以完全独立在系l之外ƈ且在不媄响系l基本功能的情况下嵌入系l?/p>
应用实例 整个例子只有四个cR应用是关于Shape的。TwoShapecLShapecȝU的基类?/p>
public abstract class TwoDShape { protected double x, y; protected TwoDShape(double x, double y) { this.x = x; this.y = y; } public double getX() { return x; } public double getY() { return y; } public double distance(TwoDShape s) { double dx = Math.abs(s.getX() - x); double dy = Math.abs(s.getY() - y); return Math.sqrt(dx*dx + dy*dy); } public abstract double perimeter(); public abstract double area(); public String toString() { return (" @ (" + String.valueOf(x) + ", " + String.valueOf(y) + ") "); } } TwoShapecL两个子类QCircle和Square public class Circle extends TwoDShape { protected double r; public Circle(double x, double y, double r) { super(x, y); this.r = r; } public Circle(double x, double y) { this( x, y, 1.0); } public Circle(double r) { this(0.0, 0.0, r); } public Circle() { this(0.0, 0.0, 1.0); } public double perimeter() { return 2 * Math.PI * r; } public double area() { return Math.PI * r*r; } public String toString() { return ("Circle radius = " + String.valueOf(r) + super.toString()); } } public class Square extends TwoDShape { protected double s; // side public Square(double x, double y, double s) { super(x, y); this.s = s; } public Square(double x, double y) { this( x, y, 1.0); } public Square(double s) { this(0.0, 0.0, s); } public Square() { this(0.0, 0.0, 1.0); } public double perimeter() { return 4 * s; } public double area() { return s*s; } public String toString() { return ("Square side = " + String.valueOf(s) + super.toString()); } } Tracing版本一 首先我们直接实现一个Tracecdƈ不用方面。公共接口Trace.java public class Trace { public static int TRACELEVEL = 0; public static void initStream(PrintStream s) {...} public static void traceEntry(String str) {...} public static void traceExit(String str) {...} } 如果我们没有AspectJQ我们需要在所有需要跟t的Ҏ或构造子中直接调用traceEntry和traceExitҎq且初试化TRACELEVEL和输出流。以上面的例子来_如果我们要跟t所有的Ҏ调用Q包括构造子Q则需?0ơ的Ҏ调用q且q要时刻注意没有漏掉什么方法,但是使用斚w我们可以一致而可靠的完成。TraceMyClasses.java aspect TraceMyClasses { pointcut myClass(): within(TwoDShape) || within(Circle) || within(Square); pointcut myConstructor(): myClass() && execution(new(..)); pointcut myMethod(): myClass() && execution(* *(..)); before (): myConstructor() { Trace.traceEntry("" + thisJoinPointStaticPart.getSignature()); } after(): myConstructor() { Trace.traceExit("" + thisJoinPointStaticPart.getSignature()); } before (): myMethod() { Trace.traceEntry("" + thisJoinPointStaticPart.getSignature()); } after(): myMethod() { Trace.traceExit("" + thisJoinPointStaticPart.getSignature()); } } q个斚w在合适的时候调用了跟踪Ҏ。根据此斚wQ跟t方法在Shape{中每个方法或构造子的入口和出口处调用,输出的是各个Ҏ的签名。因为方法签名是静态信息,我们可以利用thisJoinPointStaticPart对象获得。运行这个方面的mainҎ可以获得以下输出Q?/p>
--> tracing.TwoDShape(double, double) <-- tracing.TwoDShape(double, double) --> tracing.Circle(double, double, double) <-- tracing.Circle(double, double, double) --> tracing.TwoDShape(double, double) <-- tracing.TwoDShape(double, double) --> tracing.Circle(double, double, double) <-- tracing.Circle(double, double, double) --> tracing.Circle(double) <-- tracing.Circle(double) --> tracing.TwoDShape(double, double) <-- tracing.TwoDShape(double, double) --> tracing.Square(double, double, double) <-- tracing.Square(double, double, double) --> tracing.Square(double, double) <-- tracing.Square(double, double) --> double tracing.Circle.perimeter() <-- double tracing.Circle.perimeter() c1.perimeter() = 12.566370614359172 --> double tracing.Circle.area() <-- double tracing.Circle.area() c1.area() = 12.566370614359172 --> double tracing.Square.perimeter() <-- double tracing.Square.perimeter() s1.perimeter() = 4.0 --> double tracing.Square.area() <-- double tracing.Square.area() s1.area() = 1.0 --> double tracing.TwoDShape.distance(TwoDShape) --> double tracing.TwoDShape.getX() <-- double tracing.TwoDShape.getX() --> double tracing.TwoDShape.getY() <-- double tracing.TwoDShape.getY() <-- double tracing.TwoDShape.distance(TwoDShape) c2.distance(c1) = 4.242640687119285 --> double tracing.TwoDShape.distance(TwoDShape) --> double tracing.TwoDShape.getX() <-- double tracing.TwoDShape.getX() --> double tracing.TwoDShape.getY() <-- double tracing.TwoDShape.getY() <-- double tracing.TwoDShape.distance(TwoDShape) s1.distance(c1) = 2.23606797749979 --> String tracing.Square.toString() --> String tracing.TwoDShape.toString() <-- String tracing.TwoDShape.toString() <-- String tracing.Square.toString() s1.toString(): Square side = 1.0 @ (1.0, 2.0) Tracing版本?/p>
版本二实C可重用的tracing斚wQ其不仅仅用于Shape的例子。首先定义如下的抽象斚wTrace.java abstract aspect Trace { public static int TRACELEVEL = 2; public static void initStream(PrintStream s) {...} protected static void traceEntry(String str) {...} protected static void traceExit(String str) {...} abstract pointcut myClass(); } Z使用它,我们需要定义我们自q子类?/p>
public aspect TraceMyClasses extends Trace { pointcut myClass(): within(TwoDShape) || within(Circle) || within(Square); public static void main(String[] args) { Trace.TRACELEVEL = 2; Trace.initStream(System.err); ExampleMain.main(args); } } 注意我们仅仅在类中声明了一个切点,它是类中声明的抽象切点的具体实现。版本二的Tracecȝ完整实现如下 abstract aspect Trace { // implementation part public static int TRACELEVEL = 2; protected static PrintStream stream = System.err; protected static int callDepth = 0; public static void initStream(PrintStream s) { stream = s; } protected static void traceEntry(String str) { if (TRACELEVEL == 0) return; if (TRACELEVEL == 2) callDepth++; printEntering(str); } protected static void traceExit(String str) { if (TRACELEVEL == 0) return; printExiting(str); if (TRACELEVEL == 2) callDepth--; } private static void printEntering(String str) { printIndent(); stream.println("--> " + str); } private static void printExiting(String str) { printIndent(); stream.println("<-- " + str); } private static void printIndent() { for (int i = 0; i < callDepth; i++) stream.print(" "); } // protocol part abstract pointcut myClass(); pointcut myConstructor(): myClass() && execution(new(..)); pointcut myMethod(): myClass() && execution(* *(..)); before(): myConstructor() { traceEntry("" + thisJoinPointStaticPart.getSignature()); } after(): myConstructor() { traceExit("" + thisJoinPointStaticPart.getSignature()); } before(): myMethod() { traceEntry("" + thisJoinPointStaticPart.getSignature()); } after(): myMethod() { traceExit("" + thisJoinPointStaticPart.getSignature()); } } 它与版本一的不同包括几个部分。首先在版本一中Trace用单独的cL实现而方面是针对特定应用实现的,而版本二则将Trace所需的方法和切点定义融合在一个抽象方面中。这样做的结果是traceEntry和traceExitҎ不需要看作是公共ҎQ它们将由方面内部的通知调用Q客户完全不需要知道它们的存在。这个方面的一个关键点是用了抽象切点Q它其实与抽象方法类|它ƈ不提供具体实现而是由子斚w实现它?/p>
Tracing版本?/p>
在前一版本中,我们traceEntry和traceExitҎ隐藏在方面内部,q样做的好处是我们可以方便的更改接口而不影响余下的代码?/p>
重新考虑不用AspectJ的程序。假设,一D|间以后,tracing的需求变了,我们需要在输出中加入方法所属对象的信息。至有两种Ҏ实现Q一是保持traceEntry和traceExitҎ不变Q那么调用者有责Q处理昄对象的逻辑Q代码可能如?/p>
Trace.traceEntry("Square.distance in " + toString()); 另一U方法是增强Ҏ的功能,d一个参数表C对象,例如 public static void traceEntry(String str, Object obj); public static void traceExit(String str, Object obj); 然而客户仍然有责Q传递正的对象Q调用代码如?/p>
Trace.traceEntry("Square.distance", this); q两U方法都需要动态改变其余代码,每个对traceEntry和traceExitҎ的调用都需要改变?/p>
q里体现了方面实现的另一个好处,在版本二的实CQ我们只需要改变Trace斚w内部的一部分代码,下面是版本三的Trace斚w实现 abstract aspect Trace { public static int TRACELEVEL = 0; protected static PrintStream stream = null; protected static int callDepth = 0; public static void initStream(PrintStream s) { stream = s; } protected static void traceEntry(String str, Object o) { if (TRACELEVEL == 0) return; if (TRACELEVEL == 2) callDepth++; printEntering(str + ": " + o.toString()); } protected static void traceExit(String str, Object o) { if (TRACELEVEL == 0) return; printExiting(str + ": " + o.toString()); if (TRACELEVEL == 2) callDepth--; } private static void printEntering(String str) { printIndent(); stream.println("Entering " + str); } private static void printExiting(String str) { printIndent(); stream.println("Exiting " + str); } private static void printIndent() { for (int i = 0; i < callDepth; i++) stream.print(" "); } abstract pointcut myClass(Object obj); pointcut myConstructor(Object obj): myClass(obj) && execution(new(..)); pointcut myMethod(Object obj): myClass(obj) && execution(* *(..)) && !execution(String toString()); before(Object obj): myConstructor(obj) { traceEntry("" + thisJoinPointStaticPart.getSignature(), obj); } after(Object obj): myConstructor(obj) { traceExit("" + thisJoinPointStaticPart.getSignature(), obj); } before(Object obj): myMethod(obj) { traceEntry("" + thisJoinPointStaticPart.getSignature(), obj); } after(Object obj): myMethod(obj) { traceExit("" + thisJoinPointStaticPart.getSignature(), obj); } } 在此我们必须在methods切点排除toStringҎ的执行。问题是toStringҎ在通知内部调用Q因此如果我们跟t它Q我们将陷入无限循环中。这一点不明显Q所以必d写通知时格外注意。如果通知回调对象Q通常都回存在循环的可能性?/p>
事实上,单的排除q接点的执行q不够,如果在这之中调用了其他跟t方法,那么必L供以下限?/p>
&& !cflow(execution(String toString())) 排除toStringҎ的执行以及在q之下的所有连接点?/p>
MQؓ了实现需求的改变我们必须在Trace斚w中做一些改变,包括切点说明。但是实现的改变只局限于Trace斚w内部Q而如果没有方面,则需要更Ҏ个应用类的实现?br />
Q来源:http://befresh.blogbus.com/logs/2004/08/339330.htmlQ?br />
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=15565Q?/p>
JMS始终在JavaEE五花八门的协议里QWebService满天飞的时候占一位置Q是因ؓQ?/p>
ActiveMQ SpringSide 2.0 全部代码于examples\bookstore\src\java\org\springside\bookstore\components\activemq 目录中?/p>
一个JMS场景通常需要三者参与: SpringSide 2.0 ActiveMQ4.1 响应Spring 2.0号召Q支持了引入XML Schema namespace的简单配|语法,化了配置的语句?nbsp; 在ApplicationContext.xml(Spring的配|文?中引入ActiveMQ的XML Scheam 配置文g),如下: ׃ActiveMQ4.1 SnapShot的那个XSD有部分错误,因此使用的是自行修改q的XSD?/p>
先在ClassPath根目录放一个修改过的activemq-core-4.1-incubator-SNAPSHOT.xsd?/p>
在ClassPath 下面建立META-INF\spring.schemas 内容如下。这个spring.schemas是spring自定义scheam的配|文?h?http:\://"部分写法 1. 配置ActiveMQ Broker 暂时采用在JVM中嵌入这U最单的模式Q?nbsp; 当spring初始化时候,ActiveMQ embedded Broker ׃启动了?/p>
2. 配置(A)ConnectionFactory ׃前面配置的Broker是JVM embedded 所以URL?vm://localhost 3 配置(B)Queue 4. 配置(C)Converter 配置ConveterQ得Producer能够直接发送Order对象Q而不是JMS的Message对象?/p>
1 配置JmsTemplate Spring提供的TemplateQ绑定了(A)ConnectionFactory?C)Converter?/p>
2.Producer 消息发送者,使用JmsTemplate发送消息,l定了JmsTemplate (含A、C)?B)Queue?/p>
1.接收处理?MDP) 使用Spring的MessageListenerAdapterQ指定负责处理消息的POJO及其Ҏ名,l定(C)Converter?/p>
2. listenerContainer 负责调度MDPQ?nbsp;l定(A) connectionFactory, (B)Queue和MDP?/p>
互相l定的关pLҎQ发送端和接收端都以不同形式l定?A) connectionFactory, (B)Queue?(C)Converter?/p>
请先阅读ActiveMQ4.1 +Spring2.0的POJO JMSҎ(? 本篇补充说明了Q?/p>
1) 使用数据库持久化消息Q保证服务器重启时消息不会丢?br />
2) 使用Jencks作正宗的JCA Container?/p>
在配|文件applicationContext-activemq-embedded-persitence.xml中的<amq:broker>节点加入 h意MSSQL(2000/2005)和HSQL׃不支持[SELECT * ACTIVEMQ_LOCK FOR UPDATE ]语法,因此不能使用默认的userDatabaseLock="true",只能讄成useDatabaseLock="false" 配置多种数据?ljdbcPersistenceAdapter使用QSpringSide 中用的内嵌HSQL W者仅仅用了jdbcPersistenceAdapter,其实在ActiveMQ的XSD已经描述了多UPersistenceAdapter,可以参考对应的XSD文g. 另外对于数据库的差异主要表现在设|了userDatabaseLock="true"之后QActiveMQ使用的[SELECT * ACTIVEMQ_LOCK FOR UPDATE] 上面Q会D一些数据库出错(试中MSSQL2000/2005,HSQL都会D出错)。另外HSQL的脚本请参见activemq.script?/p>
Spring 2.0本n使用DefaultMessageListenerContainer 可以充当MDP中的Container角色Q但是鉴于Jencks是JCA标准的,它不仅仅能够提供jms的jca整合,包括其他资源比如jdbc都可以做到jca理 所?同时完成了这个ActiveMQ+Spring+Jencks 配置演示,更多的针对生产系l的JCAҎ展C?会在E后的开发计划讨Z定?/p>
此文档适用于说明?Jecncks ?使用Spring 2.0(DefaultMessageListenerContainer) 充当MDP Container时的区别Q同时演CJecnks 的Spring 2.0 新配|实例?/p>
在ApplicationContext.xml(Spring的配|文?中引入ActiveMQ ResourceAdapter 和Jencks 的XML Scheam 配置文g),如下: ActiveMQ4.1 响应Spring 2.0号召Q支持了引入XML Schema namespace的简单配|语法,化了配置的语句?nbsp; 在ApplicationContext.xml(Spring的配|文?中引入ActiveMQ的XML Scheam 配置文g),如下: ׃ActiveMQ RA和Jencks 那个XSD 仍然有部分错误,因此使用的是自行修改q的XSD?是xs:any元素引v的错? 先在ClassPath根目录放一个修改过的activemq-ra-4.1-incubator-SNAPSHOT.xsd和jencks-1.3.xsd?/p>
同样修改 ClassPath 下面META-INF\spring.schemas 增加内容如下。这个spring.schemas是spring自定义scheam的配|文?h?http:\://"部分写法 1. 配置ActiveMQ Broker 参见 ActiveMQ+Spring 2. 配置ActiveMQ Resource Adapter 3. 配置Jencks 基础配置 具体的配|可以参见Jencks的XSD 4. 配置lJmsTemplate使用的connectionFactory (主要是生成?发送?使用) q里注意?在配|jmsTemplate的用的targetConnectionFactory是使用jencks配置的connectionManager 5. 配置Spring 2.0的MessageListenerAdapter,保证不需要用户实现MessageListener ?span class="nobr">ActiveMQ+Spring 6.配置Jecnks 充当MDP的Container 是把上面的MessageListenerAdapter配置到Jencks里面,完成整个MDP的配|?/p>
]]>[……]在这个时期内Q我们将见证多种语言在同一个项目上的应用,Z像现在选择框架一PҎ功能来选择相应的语a?/blockquote>
?0q代末期Qh们很难让各个语言之间紧密C操作。这些年来,Z׃很大_֊创徏出可以让不同语言紧密共存的环境。脚本语a在传l上与C语言有着很密切的关系。在JVM和CLRq_上也有hZ操作p了大量精力。另外h们也在类库上投入了很多h力物力,为的是让语言忽视cd的存在?/blockquote>
]]>
]]>
阅读全文
]]>AspectJ
一、AspectJ概述
二、AspectJ应用范围
首先让我们看看如何增加一个程序内部工作的可视性。我们定义一个简单的斚w用于代码跟踪q且在每个方法调用时输出一些信息。在前一的囑Ş~辑例子中,q样的方面可能仅仅简单的跟踪什么时候画一个点?/p>
pointcut tracedCall():
call(void FigureElement.draw(GraphicsContext));
before(): tracedCall() {
System.out.println("Entering: " + thisJoinPoint);
}
}
代码利用了thisJoinPoint变量。在所有的通知体内Q这个变量将与描q当前连接点的对象绑定。所以上qC码在每次一个FigureElement对象接受到drawҎ时输出如下信息:
许多的程序员使用按契U编E?Design by Contract)的Ş式。这UŞ式的~程需要显式的前提条g试以保证方法调用是否合适,q需要显式的后箋条g试保证Ҏ是否工作正常。AspectJ使得可以模块化地实现q两U条件测试。例如下面的代码
Z属性的横切机制在定义更加复杂的合同实施上非常有用。一个十分强大的功能是它可以强制特定的方法调用只出现在对应的E序中,而在其他E序中不出现。例如,下面的方面实施了一个限Ӟ使得只有在知名的工厂Ҏ中才能向注册q添加FigureElement对象。实施这个限制的目的是ؓ了确保没有Q何一个FigureElement对象被注册多ơ?/p>
AspectJ的配|管理可以用类gmake-file{技术进行处理。程序员可以单的包括他们惌的方面进行编译。不惌M斚w出现在品阶D늚开发者也可以通过配置他们的make-file使用传统的Java~译器编译整个应用?/p>
在第一个例子,斚w的角色是用于l护一位数据标志,由它说明对象从最后一ơ显C刷新开始是否移动过。在斚w中实现这L功能是十分直接的QtestAndClearҎ被显CZ码调用以便找C个图形元素是否在最q移动过。这个方法返回标志的状态ƈ它讄为假。切点move捕捉所有能够是囑ŞUd的方法调用。After通知截获move切点q设|标志位?/p>
横切l构的上下文传递在JavaE序中是十分复杂的一部分。考虑实现一个功能,它允许客戯|所创徏的图形对象的颜色。这?a target="_new">需?/a>需要从客户?/a>传入一个颜色或颜色工厂。而要在大量的Ҏ中加入一个参敎ͼ目的仅仅是ؓ传递上下文信息q种不方便的情况是所有的E序员都十分熟悉的?/p>
接下来的例子说明了基于属性的斚w如何在很多操作中提供一致的处理功能。这个方面确保包com.bigboxco的所有公共方法记录由它们抛出的Q何错误。PublicMethodCall切点捕捉包中的公共方法调用, after通知在Q何一个这U调用抛出错误后q行q且记录下这个错误?/p>
三、AspectJ的高U特?/strong>
... aspect body
}
]]>
的特性:
1.2 SpringSide 的完全POJO的JMSҎ
在BookStoreCZ中,演示了用户下订单Ӟ发通知信到用户邮箱的动作,通过JMS交给JMS服务端异步完成,避免了邮件服务器的堵塞而媄响用L下订?/p>
采用了ActiveMQ 4.1-incubator 与Spring 2.0 集成Q对比SS1.0M3Q有三个值得留意的地方,使得代码中几乎不见一丝JMS的R入代码:
Q充当MDP Container的角艌Ӏ?
2.引入ActiveMQ的XSD
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.org/config/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://activemq.org/config/1.0 http://people.apache.org/repository/org.apache.activemq/xsds/activemq-core-4.1-incubator-SNAPSHOT.xsd">
http\://people.apache.org/repository/org.apache.activemq/xsds/activemq-core-4.1-incubator-SNAPSHOT.xsd=/activemq-core-4.1-incubator-SNAPSHOT.xsd
3. 配置Ҏ
3.1 基础零g
<!-- lets create an embedded ActiveMQ Broker -->
<amq:broker useJmx="false" persistent="false">
<amq:transportConnectors>
<amq:transportConnector uri="tcp://localhost:0"/>
</amq:transportConnectors>
</amq:broker>
<!-- ActiveMQ connectionFactory to use -->
<amq:connectionFactory id="jmsConnectionFactory" brokerURL="vm://localhost"/>
<!-- ActiveMQ destinations to use -->
<amq:queue name="destination" physicalName="org.apache.activemq.spring.Test.spring.embedded"/>
<!-- OrderMessage converter -->
<bean id="orderMessageConverter" class="org.springside.bookstore.components.activemq.OrderMessageConverter"/>
3.2 发送端
<!-- Spring JmsTemplate config -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<!-- lets wrap in a pool to avoid creating a connection per send -->
<bean class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="jmsConnectionFactory"/>
</bean>
</property>
<!-- custom MessageConverter -->
<property name="messageConverter" ref="orderMessageConverter"/>
</bean>
<!-- POJO which send Message uses Spring JmsTemplateQ绑定JMSTemplate 与Queue -->
<bean id="orderMessageProducer" class="org.springside.bookstore.components.activemq.OrderMessageProducer">
<property name="template" ref="jmsTemplate"/>
<property name="destination" ref="destination"/>
</bean>
3.3 接收?/h3>
<!-- Message Driven POJO (MDP)Q绑定Converter -->
<bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
<constructor-arg>
<bean class="org.springside.bookstore.components.activemq.OrderMessageConsumer">
<property name="mailService" ref="mailService"/>
</bean>
</constructor-arg>
<!-- may be other method -->
<property name="defaultListenerMethod" value="sendEmail"/>
<!-- custom MessageConverter define -->
<property name="messageConverter" ref="orderMessageConverter"/>
</bean>
<!-- this is the attendant message listener container -->
<bean id="listenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="destination" ref="destination"/>
<property name="messageListener" ref="messageListener"/>
</bean>
4. 下篇
1. 说明
2.持久化消?/h2>
2.1 lBroker加入Persistence 配置
<amq:persistenceAdapter>
<amq:jdbcPersistenceAdapter id="jdbcAdapter" dataSource="#hsql-ds" createTablesOnStartup="true" useDatabaseLock="false"/>
</amq:persistenceAdapter>
2.2 配置多种数据?/h3>
<!-- The HSQL Datasource that will be used by the Broker -->
<bean id="hsql-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:res:hsql/activemq"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
<property name="poolPreparedStatements" value="true"/>
</bean>
2. 3 说明
3. Jenck(JCA Container)
3.1 引入ActiveMQ ResourceAdapter 和Jencks 的XSD
<beans
xmlns="http://www.springframework.org/schema/beans" xmlns:amq="http://activemq.org/config/1.0" xmlns:ampra="http://activemq.org/ra/1.0" xmlns:jencks="http://jencks.org/1.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://activemq.org/config/1.0 http://people.apache.org/repository/org.apache.activemq/xsds/activemq-core-4.1-incubator-SNAPSHOT.xsd
http://activemq.org/ra/1.0 http://people.apache.org/repository/org.apache.activemq/xsds/activemq-ra-4.1-incubator-SNAPSHOT.xsd
http://jencks.org/1.3 http://repository.codehaus.org/org/jencks/jencks/1.3/jencks-1.3.xsd">
http\://people.apache.org/repository/org.apache.activemq/xsds/activemq-ra-4.1-incubator-SNAPSHOT.xsd=/activemq-ra-4.1-incubator-SNAPSHOT.xsd
http\://repository.codehaus.org/org/jencks/jencks/1.3/jencks-1.3.xsd=/jencks-1.3.xsd
3.2 配置Ҏ
3.2.1 基础零g
<amqra:managedConnectionFactory id="jmsManagedConnectionFactory" resourceAdapter="#resourceAdapter"/><amqra:resourceAdapter id="resourceAdapter" serverUrl="vm://localhost" />
<!-- jencks PoolFactory config-->
<jencks:singlePoolFactory id="poolingSupport" maxSize="16" minSize="5" blockingTimeoutMilliseconds="60" idleTimeoutMinutes="60" matchOne="true" matchAll="true" selectOneAssumeMatch="true" /> <!-- jencks XATransactionFactory -->
<jencks:xATransactionFactory id="transactionSupport" useTransactionCaching="true" useThreadCaching="true" />
<!-- jencks ConnectionManagerFactory -->
<jencks:connectionManagerFactory id="connectionManager" containerManagedSecurity="false" poolingSupport="#poolingSupport" transactionSupport="#transactionSupport" /> <!-- jencks TransactionContextManagerFactory -->
<jencks:transactionContextManagerFactory id="transactionContextManagerFactory"/>
<!-- spring config jms with jca-->
<bean id="jmsManagerConnectionFactory" class="org.springframework.jca.support.LocalConnectionFactoryBean">
<property name="managedConnectionFactory">
<ref local="jmsManagedConnectionFactory" />
</property>
<property name="connectionManager">
<ref local="connectionManager" />
</property>
</bean>
<!-- Spring JmsTemplate config -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<!-- lets wrap in a pool to avoid creating a connection per send -->
<bean class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="jmsManagerConnectionFactory" />
</bean>
</property>
<!-- custom MessageConverter -->
<property name="messageConverter" ref="orderMessageConverter" />
</bean>
<!-- Jencks Container-->
<jencks:jcaContainer> <jencks:bootstrapContext>
<jencks:bootstrapContextFactory threadPoolSize="25" />
</jencks:bootstrapContext>
<jencks:connectors>
<!-- use jencks container (use spring MessageListenerAdapter)-->
<jencks:connector ref="messageListener">
<jencks:activationSpec>
<amqra:activationSpec destination="org.apache.activemq.spring.Test.spring.embedded" destinationType="javax.jms.Queue" />
</jencks:activationSpec>
</jencks:connector> </jencks:connectors> <jencks:resourceAdapter>
<amqra:resourceAdapter serverUrl="vm://localhost" />
</jencks:resourceAdapter>
</jencks:jcaContainer>
]]>
直板反胶正手拉球的基本原理和训练Ҏ
乒乓球基本上是一圆周运动,正手和反手拉球都是以q动员的w体重心u心、以w体到n体重心的q线为半径进行圆周运动。因此,不管是正手还是反手击球都必须W合q个原理Q从q个意义上讲Q正手拉球动作的基本原理是一U力的传递?
正手拉球的基本要?
基本站位Q两腿张开与肩的宽度ؓ差不多相同,w体E微前倾,重心在前脚掌上,拉球Ӟw体向右转(以右手ؓ例)Q重心放在右脚上Q在转腰的过E中Q用腰控制大臂,双E底Q小臂自然下垂,用手腕控制板型,板型前倾(拇指用力压住球板Q食指稍微放松,中指住球板Q,板型前倄角度因来球的旋{不同而调整?
ȝ原理Q击球的时候,以右手ؓ例,首先是腿上发力,向左y腿Qn体重心从双向左脚{换,交换重心Qn体前q,w体前迎的方向要和击球的方向一致。然后是C发力Q用腰带动大臂{动,把力传递到前臂Q在ȝ一瞬间Q收~前臂用力击球。从力学的原理讲Q正手拉球前Q小臂和大臂之间的角度越越好,q是加大半径Q半径越大,初速度p大,在击球瞬间突然收~前臂,使半径变而获得加速度Q速度加快Q力量加大。击球时Q小臂和大臂之间角度的变化要Ҏ来球和击球的需要进行变化。很多运动员在进行正手拉球时往往只注意了收前臂而忽略了转腰Q用腰来控制手臂的发力,或者是注意了用腰的发力来带动手臂而忽略了收前臂,前臂和大臂之间的角度几乎没有变化或变化很。ȝh正手拉球应注意四点:1、必L意重心的交换Q重心迎前的方向要和ȝ的方向一致?、一定要用腰控制大臂Q是C发力Q而不是用手臂发力Q注意拉球时ѝ腰、大臂、前臂、手腕发力的协调?、击球瞬间必d速收~前臂、手腕发力,前臂收羃的速度快Q发出的力量p大?、击球点必须保持在n体的叛_方,ȝ点离w体近Q越Ҏ控制球。有一点值得注意的是不管是什么样的拉球动作,必须和你自n具备的n体条件相W合Q只要不影响动作的发力就可以Q没有什么固定的动作模式。另外就是在ȝ前,球板和球之间要有一定的距离Q尽量主动去ȝQ而不要让球来撞你的球拍,或者是球与球拍之间的距d,Ҏ被来球顶住,影响你的发力?
正手拉球的方法与技?
正手拉球是一门很复杂的技术,有近台拉球、中q台拉球、远台拉球,有拉上旋球、下旋球Q有q台快带、反拉弧圈球Q拉半出台球{等。不拉球有多么复杂Q但有一Ҏ最重要的基Q就是步法。步法的好坏Q直接关pd正手拉球的命中率、力量的大小和拉球时的调节能力。要想练好正手拉球,必dl好步法。而在q一点上Q是专业q动员和业余q动员最大的区别所在,业余q动员不可能像专业运动员那样q行大量的高强度的步法训l。但有一Ҏ相同的,那就是击球的技巧。只要能够做到因势利|充分发挥现有的条Ӟ也会收到一定的效果。下面,我给大家介绍一些比较实用的训练Ҏ和技巧:
1、拉好定点下旋球Q拉冲下旋球是直板反胶最基础的基本功Q在拉下旋球旉了注意前面提到的基本动作要领以外Q要特别注意手腕的用力方法。在ȝ的瞬间是用手腕去摩擦球,ȝ点在来球的中上部Q在用手腕摩擦球时还要根据来球旋转的强弱再加上一定的撞击。就是h们常说的又摩又打。拉冲下旋球旋{q来球要连摩擦带撞击,撞击可稍大于摩擦。拉冲下旋球旋{强的来球必须用力摩擦ȝQ用自己拉球的力量抵消来球的旋{。在ȝ的瞬间要特别注意ȝ时一定要把球往前送,不能靠力量去碰球。这是我们常说?#8220;吃球”Q尽量让球在球板上停留的旉长一些。经常这栯l拉球,你对球的感觉׃来好Q拉球就会越来越有数Q慢慢达到运用自如。训l的ҎQ在没有多球条g的情况下可采用拉球一方发下旋球到Ҏ的反手位让对Ҏ长球Cw位Q然后发力拉冲这个球。拉球时一定要注意用全力拉Ԍ不要考虑下一板球Ҏ是否能够防过来。要的就是让你防不过来。经常这栯l,你的拉球力量一定会提高。在有多球的条g下,可让Ҏ发下旋球C的侧w位Q定点发力拉冲这U球。拉球时要掌握好ȝ旉Q在Ҏ来球跛_最高点或下降前期击球最好。击球时间一定要相对固定Q这样容易掌握拉球的命中率,好调节。出界多向前送一点,下网多就多摩擦一炏V在定点拉冲下旋球比较有数的情况下,再把来球的落Ҏ大到全台的定ҎԌq样不断加大拉球的难度,拉球的水q_会不断提高?
2、拉好定点上旋球Q拉上旋球和下旋球不同的是,拉上旋球ȝ点在来球的上部,摩擦球要大于撞击球,ȝ的瞬间一定要往前送。训l的Ҏ基本和抢拉下旋球一P只是来球的旋转不一P是上旋球。在推挡后侧w发力拉冲这板球Q或Ҏ变你正手位后发力拉冲Q反复练习。有多球训练的条Ӟ可以由对方直接发上旋球到你的正手位和侧n位抢Ԍ落点可以从定点到不定点,逐步提高ȝ的难度?
3、练好反拉弧圈球Q反拉弧圈球是一U高U技术,其是业余运动员掌握了这Ҏ术就像如鱼得_你就掌握了比赛的d权。因Z般的业余q动员在拉弧圈球时拉高吊弧圈球的时候多Q你掌握了反拉弧圈球的技术,你就站在了比Ҏ高一挡的层次上。反拉弧圈球的要领,首先要自己发力,量借对方的旋{Q用自己拉球的力量去抉|Ҏ来球的旋转。其ơ是在反拉时摩擦球一定要薄,摩擦球的上部甚至剙Q既要借对Ҏ球的旋{的力Q还要自己发力摩擦球。越是自己发力反拉,命中率越高。越是怕对方的旋{ȝ球,是Ҏ吃对方的旋{。训l的ҎQ对方发下旋球到你的反手位,你搓球到Ҏ侧n位,Ҏ拉高吊弧圈球C反手位,你侧w反拉,q样反复l习Q等基本掌握了反拉弧圈球的规律以后,再把反拉扩大到全台和不定点反拉?
4、近台正手快带弧圈球Q这Ҏ术是防守中很先进的技术,也是很难掌握的技术,?0q代后期才逐渐被采用的技术。在q之前h们在正手位的防守都是qxQ借对Ҏ球的旋{把球挡过去,因而在比赛关键的时d很容易因紧张而造成pQ即使不pQ防q去的球也没有威胁,很容易被Ҏq箋q攻。到90q代后期Q中国的q动员把反拉的技术运用在q台的防守上Q特别是直板反胶打法的运动员q用更多Q加快了攻防转换的节奏,收到了很好的效果Q马林在q项技术的q用上是非常H出的。这Ҏ术要求运动员的对来球的判断要非常快、准,手上对球的感觉要求很高,因ؓ有很多球是在失去w体重心或不C的情况下Q完全靠q动员手上的功夫d成技术动作。我惌然目前在业余q动员中能真正掌握这Ҏ术的不多Q但已经具备了一定水q的q动员可以去试一下,也许你会有意外的收获?
q项技术的技巧主要在于掌握好ȝ旉和手腕的用力Q击球时间尽量在球的赯前期Q上升期Q,当步法实在到不了位的情况下,q可以在球刚一跌v时就ȝ。击球时靠腰和手腕发力,接触球的剙。接触球时既要借对Ҏ球旋转的力,同时自己一定要发力L擦球Q尽量摩擦薄一点,摩擦厚就Ҏ下网Q在摩擦球的瞬间一定要把球往前顶。训l方法可采用搓下旋球到对Ҏ手位让对Ҏ弧圈球到自己的正手位Q然后正手近台快带。这样反复练习就会逐渐掌握ȝ的基本方法,在快带对方从下旋球拉h的弧圈球比较熟练的情况下Q再q行推直U让Ҏ拉弧圈球到自q正手位快带上旋弧圈球的训l。这P你就会慢慢掌握在防守中正手近台快带弧圈球的技术。这Ҏ术的关键Ҏ在击球时一定摩擦球要薄Q而且自己一定要d发力d球?
正手拉球的注意事?
业余选手在练习正手拉球时Q要注意掌握以下几点Q?
1、收前臂Q在正手拉球时一定要注意收前臂,大臂和小臂之间的角度一定不能固定,要根据来球来军_摆臂的大。但要注意一点,收前臂一定要用腰来控制?
2、{腎ͼ׃乒乓球是圆周q动Q击球时用腰来控制手是非帔R要的环节Q击球时球拍的后引不是用手往后拉手,而是用{腰来完成Q用腰固定大臂,转腰的速度要远q快于拉手。就是说Q在ȝ前的摆臂是先转腰而不是先拉手。而我们好多球q们在打球时都是先拉手,不知道{腎ͼ因而在ȝ时经常出现n体不协调D发力不集中或发不出力?
3、击球点Q击球点的最佳位|是在n体的叛_方(以右手ؓ例)Q要保持最佳的ȝ位置必d好步法,保持好n体的重心Q重心的高低要根据来球来军_。马林经怋用的侧n倒地爆冲是不得已而ؓ之,Ҏ搓过来的球又低又长,拉完以后不可能再q原Q只有搏杀。马林在拉这U球的时候重心低Q但是击球点是球的最高点或下降前期。正手位大角度的球击球点要根据自己步法移动的情况来决定击球点的高低。一般情况下是在球的下降中期和后期击球?
4、手腕的q用Q在拉球Ӟ手腕要相对固定,不能晃动太大Q击球瞬间用中指住球板发力摩擦球。另外手腕还hȝ瞬间的调节功能,比如在拉球时H然感到球的旋{比自己预想的要{时就靠手腕来调节ȝ的力量大和摩擦球的部位。在不到位和住自己的情况下Q就要靠腰和手腕来调节击球点。特别是在比赛中Q很多球都不是很规则Q来球的落点也是你最隑֏的地方,q时候就要靠手腕来调节,手腕的调节主要靠大拇指和中指用力来完成。其ơ拉球时板型的控制也要靠手腕来完成,有很多的直板q动员正手拉球时吊腕很厉宻Iq媄响发力,一般情况下Q手腕和前臂几乎在一条直U上Q球板把与手腕之间的角度?5度左叟?
5、吃球:我们看一个运动员拉球的好坏,主要是看他拉球时是否吃球。吃球就是球在球板上的停留时间比较长Q而不是球一球板就出去了。要做到拉球时吃球,必L一板球都主动发力去摩擦球,在^时的训练中尽量少打借力球。拉球吃球的好坏Q在qx训练中不是很明显Q但在比赛中有很大的区别。很多球都是在你不到位的情况下要完成拉球的动作,全靠你用手腕主动发力去摩擦球来调节Q你习惯了主动发力拉球,p在比赛中控制拉球时力量和ȝ部位的调节,拉过d多高隑ֺ的球?
6、抢冲上旋球和下旋球的区别:动作上没有多大的区别Q区别在于抢冲下旋球时击球点在球的中上部Q发力的时候根据来球的旋{可带Ҏ击;抢冲上旋球时ȝ点在球的剙Q主动发力摩擦球Q击球时w体重心也随之向前。特别是在反拉弧圈球Ӟ摩擦薄反而容易过去,摩擦厚或带点撞击容易失误?
7、微调:很多球迷朋友提出q个问题Q我认ؓ要在比赛中做到这一Ҏ比较隄。这首先取决于你个h本n的球感,是你手上对球的感觉。其ơ是在训l中不断地培M对球的旋转的理解Q要清楚地知道你打过ȝ球是什么样的旋转,Ҏ回过来的球又是什么样的旋转。只有这P你才会根据来球的不同Q在很困难正常击球的情况下,在来球很不规则的情况下,在球落在边边角角很难回击的情况下Q通过手上的调节把球回击过厅R因此,对于业余球迷朋友们来Ԍ最主要的是ȝ球的旋转变化,把这个规律基本掌握住了,你就具备了微调的能力
正手弧圈球技术是乒乓球技术中最基本也是最重要的技术之一。拉好弧圈球的三个要素就是腿、腰、手Q三者要协调一_才能发挥弧圈球的最大威力?
从弧圈球的风g来讲Q目前主要分为欧z派和亚z派。欧z选手拉弧圈球的时候,撞击的成分比较多Q因此球在飞行的q程中速度快,力量大,弧线低;亚洲选手拉弧圈球的时候,摩擦的成分比较多Q因此球在弹起后的过E中速度快,旋{强,弧线低。随着弧圈球技术的发展Q目前各国选手都在怺学习Q相互借鉴Q因此ƈ没有十分明显的风格区别,而是Ҏ不同的球q用不同的技术?
弧圈球的基本技术动作ƈ不难Q但是要x好弧圈球必须要勤学苦l,才能是自q技术有大幅度的提高。如何掌握基本的弧圈球技术呢Q(以右手握拍选手ZQ?
一、技术动作分?
1.准备动作Q?
拉球之前Q站位一定要合理。一般来_站位距球台边~?.5c_叟뀂左脚前Q右脚后Q两脚间距略比肩宽,双于左脚脚窝的位|^齐,以两脚前脚掌内侧着地。两腿弯Ԍ含胸Q重心放低,w体与球台边~的夹角大概?5度左叟?
2.拉球Q?
拉上旋球Ӟ双略微下沉Q同时横向{腎ͼ双自然放松Q靠横向转腰动作完成引拍的过E。此Ӟ以右脚ؓ_重心攑ֈ双上。然后,双y地Q腰部横向回转,q带动右臂,注意此时双仍ؓ放松状态。待腰{到基本与球台边缘q的时候开始收~前臂,ȝ。重心由双转移C腿上Q两肩持q뀂击球时Q要扑֥ȝ旉。击球时间分Z升期和下降期Q上升期是指来球卛_辑ֈ最高点的时候,下降期是指来球从最高点刚刚下落的时候。一般来_来球位于双部前方一多的距Lȝ感觉最好,可以发出力。击球时Q要注意摩擦球,主要向前发力。击球后要注意大臂、小臂立L松,q原?
此主题相兛_片如下:
关于ȝ部位Q对于以拉打Z和摩擦ؓL有区别的?以拉打ؓȝ选手Q击球的部位一般ؓBҎB、C点之间。以摩擦Z的选手Q击球部位一般ؓC炏V?
拉下旋球的动作要领与拉上旋球基本一致。只是拉下旋球时Q右肩沉的更低一些,ȝ的部位一般ؓB点,且用力的方向向上多一些?
3.步法
拉球Ӟ要根据来球的位置Q时刻跑动来调节ȝ的最佳位|。跑动时要保证重心尽量^EIw体不要乱晃?
二、高吊弧圈与前冲弧圈
高吊弧圈一般是针对拉下旋球而言的。高吊弧圈以旋{见长Q但是弧U略高,速度较慢。高吊弧圈的ȝ部位一般ؓB点,甚至是A、B点之_q要Ҏ来球的旋转而定。拉高吊弧圈Q右肩下沉的较低Q用力方向向上的比较多,先要刉一个高q球|的弧线Q然后用力方向向前,再制造一个向前的弧线。如果一味的向上拉Q则球很Ҏ出界?
前冲弧圈速度快,力量大,但旋转稍逊。拉前冲弧圈Q击球部位一般ؓCҎB、C点之间。右肩略微下沉,用力方向向前比较多。若来球的下旋旋转很强,则必d加{腰的q度和前臂收~的速度Q以增大对球的摩擦力?
三、台内弧圈球技?
台内弧圈球的技术难度比较大。首先要判断来球的位|和高度Q根据来球的高度来决定引拍的高度。拉台内弧圈球,一般引拍的高度较高Q往往与台面高度持qI甚至高于台面。击球部位一般ؓD炏V由于摩擦球的部位很薄,因ؓ对于下旋非常强的台内球,处理h隑ֺ很大。而对于不太{的下旋球来说Q台内弧圈球l对斚w成的威胁还是很大的。拉台内弧圈球,要注意用力方向向上多一些,l而向前,要把弧线拉短?
四、套胶与弧圈?
q口套胶与国产套胶的性能不同Q对于拉弧圈球的风格有一定的影响?
Ƨ洲人拉球多为拉打,因ؓƧ洲的套胶胶皮黏性差Qvl偏软,但弹性好。用进口套Ӟ球在接触到拍子之后,L被挤压的E度较深Qvl被压羃的行E长Q这样就削减了来球的大部分旋转和力量Q因此采用拉打的手法可以很好的控制来球,加之Ƨ洲n高马大,爆发力非常好。这L拉球威力不小?
亚洲人拉球多摩擦Q因为国产的套胶Q如狂飙pd套胶Q胶皮黏性强Qvl弹性非常实在,非常大。在球接触拍子的时候,胶皮l了来球很大的阻力,而vl被压羃的程度也不大Q这样就造成的脱杉K度很快。因此只有多摩擦Q以旋{克旋转才能拉出高质量的弧圈球。所以用国产套胶对拉球的技术要求较高?
随着乒乓器材的发展,国内已经生出很多新产品Q兼具了国与进口的很多优点Q对于众多的乒乓球爱好者来_又多了很多的选择?
五、拉球的常见问题
1. 重心后坐?
重心后坐Q自然腉K力量不能发挥出来Q手臂的走向多为向上,削减了拉球的速度、力量和旋{?
2. 手臂늡?
引手的过E中Q肌肉僵,大大降低了控制球的能力,q住了力量。击球后肌肉늡Q力量不能全部发挥出来Qƈ降低了还原速度?
3. 转腰不够?
只靠手臂拉球Q速度、力量、旋转都有很大的损失?
4. 抬肘、抬肩?
使腿、腰、手不能协调一_当力量从ѝ腰传到手的时候,能量中断?
5.步法q钝?
{球Qȝ点太低,使全w的力量用不到球上?/span>
]]>
拉弧圈最重要的环节是什么?是吃球?/span>
是量廉球和胶皮接触的时_d发力控球Q把挥拍的能量充分作用到球体上。吃球就是球在球板上的停留时间比较长Q而不是球一球板就出去了。要做到拉球时吃球,必L一板球都主动发力去摩擦球,在^时的训练中尽量少打借力球?/span>
廉控球旉靠是什么?反胶、Yѝ灌胶、先打后摩,q有最重要的一Ҏ在加速挥拍过E中ȝ。加速击球就好比在阻力较的q面上推子Q只有不断加速去推,才能一直不LQ力量才能充分传递到子上。也是_拉弧圈最好是不断加速追着球摩擦?/span>
如果拉上旋来球,是逆旋转击球,球和胶皮接触的瞬_球和胶皮的相寚w度大,来球减{的过E就是个~冲q程Q球不会很快脱板Q一般不会有吃不住球的感觉?/span>
如果拉下旋来球,则是旋转击球,如果挥拍向上的速度低于旋{, 便无法吃得住球。就好比玩陀螺,抓住转动的陀螺容易,因ؓ是逆旋转,而给陀螺加转就很困难,要用比陀螺更快速度的鞭子去抽。这一点对着削球手感觉最为明显,力量q没作用到球上,球就脱板了,怼有吃不住球的情况发生。如果仔l观察录像,国手们拉削球时挥拍摩擦都极快Q挥拍之所以快的就是靠发力抉|来球的旋转。对下旋来球, 挥拍速度是不能低于旋转的?/span>
拉下旋球Z证能吃住球需掌握三个要点Q?/span>
一是增大球和球板的正压力,是“又摩又打”Q增大正压力便于摩擦?/span>
二是加快向上向前的挥拍速度Q包括手腕也要加上摩擦球的动作?/span>
三是掌握ȝ旉。一般是在下降期拉,一斚w下旋球在IZ飞行时会逐渐减{Q另一斚wQ球在下落时׃下落速度和球的旋转方向相反,两个速度相抵Q挥拍相寚w度׃现的更快一些?/span>
W一板从下旋拉v的弧圈很N守,也是因ؓh?#8220;旋”的加成效果。一旦练成,对对手威慑极大?/span>
前言Q都说下旋球下降期好拉,为甚么?什么出转没{Q都是凭感觉。请看物理学的精分析。我们对事物不仅要知其然Q也要知其所以然?/span>
如图Q球Z旋,讄拍垂直向上摩擦,与球?/span>aҎ触。假讄旋{每秒30转,直径40MMQ则a点线速度为:
V2=2πr*30 = 3.768m /sQ即如果球原地向上{Q?/span>a点的对地速度Q?/span>
1、拉上升期,a炚w度{速加球速?/span>
讄向上的分速度v0 = 2m/s.?/span>a点对于地面的速度?/span> v0+v2 = 5.768m/s .如果靠摩擦把球拉P拍速必d?/span>a炚w度。约21公里/时?/span>
2、拉下降期,a炚w度{速减球速?/span>
讄向下落的分速度v0 = 2m/s.?/span>a点对于地面的速度?/span> v0-v2 = 1.768m/s .如果靠摩擦把球拉P拍速必d?/span>a炚w度。约6.3公里/时?/span>
可见拉上升期比下降期需要三倍的速度Q?/span>
]]>
1、编辑文ӞetcQhostsQؓ该工作站加另一个网D地址Q?br />
QviQetcQhosts
127Q?Q?Q?localhost
192Q?Q?00Q?serverloghostQ本例的L名及地址
192.9.201.1 anoserverQ另一个对应的名称及地址
2、编辑文?etc/nerworks,两个网l的地址加入Q?br />
Qvi /etc/networks
loc 192.9.200;本网|址
ano 192.9.201;另一个网的网址
3、新建文?etc/gatewaysQ该文g只要存在没有内容也可Q以使SOLARIS在启动时q行路由器服务进E?br />
Qcat/dev/null>/etc/gateways
4、查询主|卡的名Uͼ
Qifconfig-a;列出pȝ中的所有网l接?br />
loO:flags=849<UP,LOOPBACK,RUN-NONG,MULTICAST>mtu 8232
inet 127.0.0.1 netmask
ff000000
hneO:flags=863<UP,BROADCAST,NO-TRAILRS,RUNNNHG,MULTICAST>mtu1500
inet 192.2.200.1 netmask ffffff00 broadcast
192.2.200.255
ether 8:0:20:1:2:3
hme即ؓ工作站上所配的100M|卡名,如果你所用的?0M|卡则名为le?br />
5、新建文?etc/hostname.hme0:1,?etc/josts中的另一个主机名填入Q以使SOLARIS启动时在物理接口hme0上徏立一个逻辑接口?br />
6、设|完以上各步后,重启工作?br />
7、效果:
在工作站启动中,可以看到“machine is a router.”的噗昄。表明本机已成ؓ一个\由器Q会向网l上发RIP包,用接口查询命令可见:
Qifcofig -a ;列出pȝ中的所有网l接?br />
lo0:flags=849<UP,LOOPBACK,RUNNNG,MULTICAST> mtu8232
inet 127.0.0 .1etmask ff00000
hne0:flags=863<UP,BROADCAST,NOTRAILERS,RUN-NING,MULTICAST>mtu 1500
inet 192.9.200.1 netmask ffff00 broadcast
192.9.200.255
hne0:1:flags=8d0<UPQBROADCASTQNOTRAULERSQRUMNNNGQMULTICAST>mtu 1500
inet 192.9.201.1 netmask ffff00 broadcast
192.9.201.255
以上表明已启动了hme0上的一个逻辑接口Q地址?92.9.201.1?br />
在别的UNIX机器上,会根据RIP包自动将该工作站加入到\p中,在PCZQ例如WIN95Q,只要在控刉板中TCP/IPM|络的网兌|ؓ该工作站的地址Q用与本机同一个网l的地址Q,可以与另一|络的机器通迅了?br />
]]>
判断意识。对付不同的来球Q应用不同的打法。若x好球Q首先应Ҏ球作出及时、准的判断。这是正还L球的前提?br />
盯球意识。盯球,是正判断的基础。不hҎ球判断不及时或错误,都是因ؓ盯球不够。运动员每打完一板球后,都应随球密切注视Ҏȝ的动作(其是击球瞬间的动作Q,q紧盯对方击出球的弧Uѝ?br />
UL意识。对Ҏ球落点和节奏不定Qؓ保在最佳的位置和时间击球,或最大限度地发挥个h的特长技术(如反手位用侧w攻Q,必须ULȝ。应明确Q打乒乓球绝不是单纯的手法问题,随技术水q的提高Q脚步移动的重要性将来明Q显、它是争取主动、抢先进ȝ有力保证?
探烦合理ȝ点位|的意识。所谓的ȝ点位|,卛_球点与n体的相对位置。各U技术动作,都有一个最适宜的击球位|。它虽有个一般的规律Q但因h而宜十分重要。所以,q动员在打球的实践中必须不断地琢与研究自己ȝ时最适宜的位|?#8230;
打、摩l合意识。打乒乓球有两个最基本的力Q一个是撞击球的力,UCؓ打;另一个是摩擦球之力,UCؓ摩。除q网大高球,可以用单U的打外Q打其它的球Q都必须是打与摩的结合。细Iv来,q里q有两层意思?br />
1、快抽时Q以打ؓ主,摩擦。打Q可增加球的速度和力量;摩,可球生上旋,上旋有利于制造合理的ȝ弧线?br />
2、制造旋转时Q如拉弧圈球Q,应以摩擦球ؓ丅R但是一呌求摩擦,势必物极必反。擦球太薄,反而用不上力,自然难以打出旋{强烈的球来。应先打后摩Q即以打的动作将球近似粘于拍面,然后再加力摩擦?br />
调节意识。无论哪U技术动作,在还M同性能的来球时Q都必须自觉地调节动作。具体可l分为:
1、力量调节意识:Ҏ来球情况Q适当调节自己的发力。来球慢且高Q发大力Q攻Ҏ搓过来的下旋球,自己发力ZQ稍借对Ҏ球之力;Ҏ拉冲不特别凶、球略向前拱Ӟ借力中发力;Ҏ发力抽或冲时Q自己应借力挡一板或对付一板,不宜发大力?br />
2、拍形调节意识:应视来球旋{与高低,适当调节拍Ş。来球低或带强烈下旋Ӟ拍ŞE后从ͼ来球不{或与可网高时Q拍形与台面垂直Q来球上旋或高于球时Q拍形前倾;
3、引拍调节意识:应视来球的快慢、高低、旋转等变化Q相应调整引拍动作的快慢、大和高低Q切忌习惯性引拍(即不看来球,打完一板球后就习惯地将球拍引至原来位置Q。如Q对Ҏq强烈上旋的弧圈球来Q应高手引拍Qƈ及时向前q球Q不要等球,更不能有向后的拉拍动作)Q对Ҏ球下旋且低,应低手引拍;Ҏ来球很快Q应减小引拍动作q度Q加快引拍速度Q来球慢且高Q应适当加大引拍q度Q以利加力抽杀?br />
4、手指调节意识:打乒乓球Q无n体何部位发力Q最后都要通过手指作用于球拍。手指是w体发力时离球最q的部位Q感觉最敏锐。在发力Ӟ手指有如镉K之梢儿,往往起到画龙点睛的作用。尤其是在发球时Q触球瞬间的技巧全在手腕、手指的发力上?br />
5、调节用力方向意识:打球Ӟ应视不同来球Q注意调节用力方向。如Q攻下旋低球Q应多向上用力;M转球Q以向前打ؓ主;L上旋强烈的加转弧圈球Ӟ应向前ƈE向下用力?br />
q原意识。每打完一板球后,应迅速调整重心,n体尽量还原至接近准备姿势Q以M一板球做好准备。有些h因缺乏此意识Q打完一板球后,w体重心、手臂和球拍较长旉地停留在l束动作上,待对方将球还击过来,往往有来不及的感觉?br />
体会ȝ动作的意识。每打一板球Q都要对整个ȝ动作有清晰的肌肉感觉和表象,其是拍触球瞬间的发力情况应该清清楚楚。打丢一板球Q应立刻回忆动作Q哪儉K了?怎样才算正确Q随着技术水q的提高Q动脑筋q应来细。如ȝ出界了,出界多少Q刚才的ȝ动作Z么把球打出界q么q?有了q种意识Q练技术才会有收获。否则,一点体会没有,技术怎么能进步?
掌握ȝ动作实质的意识。研I技术动作,要注意它的外形,但尤为重要的是应分析ȝ动作的实质。摆速快、能发力、打摩结合好、命中率高、适应来球的范围广Q即能依打不同来球的要求相应调整动作Q,q样的动作,是好动作?
?br />
ȝ动作的时I意识。分析技术动作,应从两方面入手。一是时间节奏方面,如快带弧圈,上升期击球;L弧圈球,上升后期ȝQ拉下旋球,下降期击球。二是空间位|(或几何图形的变化Q。如挥拍路线、拍形、用力方法等。在旉节奏上,q要特别讲究从引拍到向前挥拍ȝq段旉与来球的节奏合拍Q这h能打出又快又狠的球来。即在自己发力的同时Q又充分借用了对Ҏ球之力。研I与掌握q个节奏非常重要?br />
动作不断分化的意识。在技术训l中Q应不断对方的来球ȝ分类Qƈ明确回击每一cL球的Ҏ和注意事V不运动员乐于打顺手球Q来球突变,p一球,甚ؓ不快。其实,q时应好好想惻I此球与顺手球有什么不同,长了、短了?旋{ZQ还是节奏变了?弄清楚此球特点,l而明打此类球的Ҏ。这样不断将Ҏ来球区分、归c,q明打每一cȝ的不同方法,可以自己的技术越来越_Q水q亦来高?br />
动作定与变的辩证意识。来球变了,打球动作应随之而变Q但打同cȝ的动作,则是固定越好。掌握与提高技术的整个q程是,Ҏ球的区分来细Q相应打球的动作也越分化细Q但打同cȝ的动作,又越来越固定。这“固定”?#8220;变化”的统一Q就促进了技术水q的不断提高?br />
战术意识。实践中有两层含义。一是注意研I在比赛中运用战术的Ҏ。因为只有合理地q用战术Q才能技术充分发挥。二是在训练中应带着战术意识l技术。拿最单的x斜线Ҏ作例。有人在l习xҎӞ能把比赛中的打大角和攻追w的战术联系hQ有意打大角度或时而打Ҏ中\一ѝ另一人只是一呛_盲目LUѝ很明显Q前者带着战术意识l习技术的效果要好?br />
战略意识。在训练中,其是在比赛中,要有一个全局观念。如一q中有几ơ比赛?哪个比赛最重要Q每个比赛的目的和Q务都是什么?有时为参加某ơ有军_意义的大赛,q会有意攑ּ一些小的比赛。又如,对参加一ơ大赛而言Q确立参赛h员和明确重点H破口(是团体、单打,q是双打Q)Q则属带全局性的战略问题Q必认真对待。如果这些大题目未解军_Q尽你费了很大的气力,其结果也难以如愿?br />
落点意识。训l中Q特别是在比赛中Q要注意ȝ的落炏V一般情况下Q大角度球、追w球、近|小球、底UK球和似出台未出台的球的落点较好。但不同ҎQ还会因其打法和个h掌握技术的情况Q有其特D点。如左推x者,一般最怕反手底U下旋球和调叛_左的落点变化。比赛中Q既要研I自己打球的落点Q对Ҏ怕什么落点,又要注意ȝҎ回球落点的规律?br />
旋{意识。充分认识到旋{是乒乓球的重要制胜因素之一。在训练中,要自觉地提高发球、搓球、拉球、放高球{技术的旋{强度和变化。在比赛中,要善于利用旋转变化来Cؕ以至战胜Ҏ?br />
速度意识。应充分认识到速度是我国快L法的灵魂。中国选手要战胜外国选手Q主要靠的仍是速度——提早击球时_重视手腕、手指的力量Q能快则快,不能快时Q先q渡一板,争取Z再{入快?br />
变化意识。应充分认识到变化乃是乒乓球的重要制胜因素之一Q自觉、主动地变化ȝ的速度、旋转、力量、落点和弧线。比赛中Q双斚w在ؓ形成利我、不利对方的战局而变化着战术Q谁的观察能力强Q能及时察觉Ҏ的战术意图,q速变换相应的战术Q谁容易获取胜利?br />
变化ȝ节奏的意识。比赛中Q不仅应d变化落点、旋转等Q而且应主动变化击球的节奏。如原来都是上升或高Ҏ的抢ԌC动将ȝ旉后移Q拉一板上旋强烈的加{弧圈球。对方已熟悉了你原来快冲的节奏,H然变成慢一拍的加{弧圈Q往往׃上当Q又如,同一cd球,有节奏较慢的Q有节奏特快的,若再能保持拍触球前的动作量一_则效果更好,q都是有变化节奏意识的表现?br />
抢攻意识。这是积极主动的指导思想Q力争抢d先(卛_^常说的先上手Q,能抢则抢、实在不能抢Ӟ控制一板,争取下板抢。这U意识很重要。如有h的侧w攻球技术很不错Q但因~Z抢攻意识Q所以他的侧nȝ技术英雄无用武之地。兵书讲Q?#8220;两强盔RQ勇者胜?#8221;q?#8220;?#8221;字的一个重要含义就是先发制人。在弧圈球风靡世界的今天Q快攻者只搓一板就L的打法,x抢攻意识强的表现?br />
抢先发力的意识。近q来Q世界乒乓球技术朝着更加U极d的方向发展,不仅要求抢攻在先Q而且应该量争取先发力,以自己更加d?br />
q箋q攻的意识。发赯dQ应q箋q攻Q乘胜追击,直至得分。切忌攻一板后Q再无l进ȝ准备Q将已到手的d又变成了相持、甚臌动?br />
控、防、反意识。在不能dq攻或对ҎL识极强时Q应注意控制ҎQƈ做好防守的准备。在防守或相持中Q一旦有ZQ应立即转入q攻?br />
争取局部优势的意识。我的所有技术都比对方强Q这叫绝对优ѝ比赛中自然怎么打都行。但在实践中Q这U情冉|较少见。多数情冉|相对优势。这p求运动员在比赛中应自觉地争取局部优ѝ能以己之长Q打Ҏ之短Q当然最好。但有时不一定能实现此策。如Q我发球的特长是转与不{Q而对方的特短是接高抛发球。我之特长对不上Ҏ的特短。高抛发球虽为我之特短,但与Ҏ接此球相比,我还占便宜。此时用我之特短打对方特短就是最好的战术。因为我获得了局部优ѝ?br />
记球意识。比赛时Q要有意记双Ҏ术变化的q程Q对方发的什么球Q我怎么回的Q他又怎么打的……从一个球Q到整个战局的变化,要自觉地记。时间长了,׃大大提高自己的战术意识?br />
互怕意识。比赛中“?#8221;是相互的。你怕他Q他也怕你。谁能透过现象看到本质Q谁能想得好一点,谁就Ҏd。在紧张Ӟ应多惛_自己有利的方面,多想Ҏ是多么怕你Q多x术,q样可以长自己志气Q灭Ҏ威风?br />
战略上藐视对手、战术上重视Ҏ的意识。战略者,战争的全局也;战术者,战争的局部也。运动员应树立在全局或M上藐视对手、藐视困难,而在具体的局部上应重视对手、重视困隄指导思想。如Ҏ某比赛,首先应相信自p战胜ҎQƈ认真地分析对手的技术、战术、n体和心理特点。在此基上制订自q战术Q如发什么球Q怎么抢攻Q接发球注意什么,相持、领先或落后怎么打等{,一步一步、详详细l?br />
树立技术风格的意识。在技、战术训l中、应特别树立正确的技术风根{技术风|常被Mؓq动员的技?#8220;灵魂”。培M么样的技术风|直接关pdq动员的发展方向和可能达到的水^。无C实证明,一个没有鲜明技术风格的选手Q要攀M界乒坛的高峰是不可能的!
全面训练的意识。运动员应明决定其竞技能力的诸因素QŞ态、机能、素质、技术、战术、心理和智力{)Qƈ自觉地提高之。这里,应反对狭隘的技术论。有Z为,要提高乒乓球q动成WQ就应该全力抓技术,什么n体素质、心理等l统不问。结果,管训练旉l的都是技术,但技术水q的提高却难以如ѝ运动员一定要树立全面训练的观炏V?br />
抓主要矛盄意识。每一名运动员在某一时期必有一个主要矛监֪响着他整体水q的提高。谁善于捕捉之,q设法解冻I谁就会获得明昄q步。如中国乒乓队在1957q参加第二十三届世乒赛后Q发现自q打法因缺乏准性而快速、凶狠的优点难以发挥作用。之后,狠抓了提高击球准性的训练Q很快就见到了明昄效果。不善于抓主要矛盄人,不是漫无辚wQ什么都抓,是虽有重点Q但抓得不准。其l果都是一样——费力不讨好Q?br />
凶稳l合的意识。乒乓球的技术各U各P每个人的打法又各L点,但凡在比赛中有实用h值的技术,无不同时具备威胁性(Ӟ和准性(EI。威胁性,x出的球给Ҏ回球造成困难Q甚至Ҏp。准性,卛_球不p。二者相互依存,q在一定的条g下可以互相{化。我们在训练或比赛中Q一定要注意二者的l合Q决不可以偏盖全?br />
l绝招的意识。一个运动员的技术一定要有特长,即绝招,否则往往难以l对斚w成威胁Q也难以攀L术高峰。绝招,可根据个人打法的特点、n体素质的特点、心理特点和所用球拍的性能{因素有目的地确立?#8220;伤其十指Q不如断其一指?#8221;l招是L能断其一指的技术?br />
表现意识。明训l是Z比赛。运动员在^日训l就应有一U要在比赛中强烈表现自己的欲望。这如同演员Q排l节目就是ؓ了上台表演;不但要上収ͼq要演得呱呱叫。^时这U意识强烈,演出时才可能发挥。当q动员亦是同样道理?br />
重视理论的意识。运动员应充分认识到理论对实늚指导作用Q自觉地学习和钻研乒乓球q动的理论,q注意理Z实践的结合?br />
创新意识Q无论是教练员还是运动员Q都要十分重视创新。乒乓球q动的创斎ͼ应包括技术、战术、打法、训l、管理、器材设备和理论{七个方面。运动员主要是前四个斚w?br />
前意识。教l员和运动员应能预测出未来的技术发展趋势,q以此来指导训练Q自己的训l能走在现实技术的前面?br />
定量意识。运动员在训l或比赛中,应自觉地注意数量的变化。如Q?500c多少U?其中的每一圈(400cI又跑几秒Q一周到底练多少旉Q个人的竞技状态周期规律是怎样的?个h晨脉的规律是怎样的?某技术在训练中的命中率是多少Q比赛中又是多少Q一场、一局比赛的比分v伏是怎样的?切忌什么都是含含糊p?br />
档案意识。教l员和运动员应自觉地建立业务档案Q坚持写好训l日记、阶D小l及q终ȝ。每q比赛胜负各多少场?w体素质或技术测验的具体成W是多,都应分门别类记录清楚?br />
]]>