分布式环境中动态代理的应用外文翻译|计算机专业全套免费毕业设计论文网|任务书|本科毕业设计课题目作品下载|毕业设计总结范文展说明书报告指导
二00辣 年 四 月
原文正文(一)
SUMMARY
In object-oriented programming (OOP), proxies are entities that act as an intermediary between client objects and target objects. Dynamic proxies can be used to construct distributed systems that support the open implementation approach and promote code reuse. The OO paradigm supports code reuse through various ways including inheritance, polymorphism and aggregation. In this paper, we adopt a definition of software reuse restricted to reuse of code components and address the question of constructing distributed systems based on dynamic proxies. Different networking techniques and programming paradigms such as Java's Remote Method Invocation (RMI), the Common Object Request Broker Architecture (CORBA) and Java Servlets are used to implement the distributed client/server architecture. Copyright 2004 John Wiley & Sons, Ltd.
KEY WORDS: reusability; open implementation; distributed systems; proxy; meta-programming; reflection
INTRODUCTION
A proxy is a program that provides a communication bridge allowing different applications to engage and exchange data. The idea of a proxy can be utilized in many different ways: it can be used to protect applications from each other as a firewall or it can cache exchanged data as a caching proxy. Equally, a proxy can be used as a translator between applications with different communication strategies, for example, Internet and legacy systems. For the purposes of this paper. We concentrate on certain types of proxies, Java’s dynamic proxies, and show how these can be used to construct a reflection model supporting open implementation design and software reuse.
In OOP, proxies are entities that act as intermediary between client objects and target objects. To employ proxies in a reuse context, we can interpret their invocation handler as meta-objects that provide representations of applications objects. The role of a meta-object is to observe and modify the behavior of its referents, i.e. objects it represents. With meta-objects, the system architecture constitutes a two-level reflective hierarchy with proxy objects residing at the upper level, i.e. the metal-level, and providing a behavioral representation of objects at the base level. A base level object can be attached to several proxies, each of which controls one aspect of its behavior.
Proxy-based systems support the open implementation approach[1].A system following the design principle of open implementation permits its clients to take control of implementation issues of system components. This allows clients to customize the components according to their need. The idea of open implementation design is to spare the effort of ugly workarounds arising from the black-box approach where components’ implementation are imposed on the clients. Open implementations are characterized by separating applications from an optional meta-interface. The meta-interface represents a back door through which clients can tune the application code to fit their requirements. Clients’ applications provide default behaviour and remain executable without the meta-interface. Dynamic proxies allow meta-programming and can be used to customize the application behaviour after being coupled to the application through a well-defined interface.
In earlier work[2], we addressed the question of employing dynamic proxies for constructing a reflection model with the aim of implementing reusable code. The model was applied to non-distributed applications. In this paper, we extend the model to include distributed systems using different networking technologies provided by the Java 2 platform[3] and discuss examples for implementing reusable code on the server side. Reusable components, represented as classes or logically connected groups of classes, are implemented independently of, and separated from, application context. As such, coupling between reusable components and applications is reduced and as a result the level of reusability increased. Composing the precompiled reusable components with application objects, implemented at the base level on the client side, is realized at runtime by passing application objects are parameters. Decoupling is achieved by disregarding the meta-object to which base objects are attached and by invoking the methods directly on base objects, Parameter passing varies according to Java’s mechanism of sending objext data between different virtual machines running on different computers on the network. In RMI, the objects are passed as parameters of a method invoked on a remote object. In the Common Object Request Broker Architecture(CORBA), the objects are passed over the ORB(Object Request Broker), as parameters of a service method invoked on the server object implementing the method. With Java’s servlets, the base objects are sent as parameters of an HTTP request method and the client receives the result as an HTTP response. On the server side, Java’s servlets API is used to implement specialized servlets controlling access to the reusable code.
The objective of the research herein is to show that distributed systems based on dynamic proxies support open implementations and code reuse. We address the question of dynamic proxies as a vehicle for constructing a behavioural reflection model and show that the model is applicable to single Java Virtual Machine(JVM) applications as well as to distributed systems.
Figure 1.Clients request services from Target objects to fulfil their tasks.
Figure 2.A proxy can manipulate clients’request before dispatching control further
PROXIES
The role of a proxy as a communication bridge between applications has many applications in software. From a design perspective, a proxy is a design pattern[5]; it describes a general solution to common design problems that occur repeatedly in different contexts .In distributed systems, including Web applications, a proxy is a service that sits between application servers and clients. This service receives requests from clients and makes requests to servers on behalf of the clients.
Figure 1 shows a typical situation for two classes, a Client and a Target, where clients request service from Target objects to fulfil their tasks. Here, only class names are shown and UML notation is used[6].
During the software lifecycle, proxies are useful as a means by which software can accommodate new changes. For common problems like tracing , adapting new classes, and in general, adding new features to an existing system, a proxy provides an adequate solution. With a proxy , the code of existing classes need not be modified; it is desirable to avoid changing existing code since it reduces potential testing and maintenance costs. Figure 2 depicts the modified class structure representing the proxy solution. The Proxy class implements the same interface and uses a Target object as a delegate. The proxy can manipulate clients ’requests before dispatching control over to its delegate. If adapting a new class to replace Target is required, the proxy retains the client interface by implementing ITarget and delegates the client request to the object of the new class.
In a networking context, a proxy can be utilized to support security, to optimize performance or to act as a translator to support embedding legacy systems onto the Internet. As firewalls, proxies can be used for building a security layer to prevent unauthorized access to corporate Web services. Caching proxies are employed to reduce the network load as well as the server load and HTTP proxies can be used to translate clients ’HTTP requests into the native language of legacy systems and return results back as HTML pages. Proxies can also be used to implement lazy instantiation, i.e. to defer the costs of creating and initializing an object until it is actually needed.
Figure 3.Key classes involved in realizing dynamic proxies dispatch mechanism.
In addition to normal proxies, Java supports dynamic proxies. A Dynamic proxy API has been introduced in Java 2 standard Edition (J2SE) version 1.3. Normal proxy classes are usually available as byte codes after having been compiled from the corresponding Java source files. The byte codes are loaded into the JVM before proxy objects are instantiated. The byte codes of Java’s dynamic proxies, on the other hand, are generated at runtime.
Figure 3 shows the key classes of our example involving dynamic proxies. ProxyFactory creates a Proxy object and returns it back to the client by invoking the static method newProxyInstance() of the Proxy class. Method invocation on the created proxy instance dispatches control to the invoke() method of the AssociatedHandler object associated with the proxy. The binding between proxy and target objects is realized at runtime through parameter passing. The factory method createProxy() takes an object of type java.lang.object as a parameter. At runtime, and with the support of polymorphism, an object of type ITarget can be passed. The target object is then passed further upon creating an AssociatedHandler object.
There are advantages to using dynamic proxies instead of normal proxies. Firstly , from an OO design point of view, the class structure of Figure 3 exhibits less coupling between Proxy classes and Target classes when compared with the static case. There is no direct relationship between these two class groups; the coupling takes place dynamically at the object level. In fact, the type of the created dynamic proxy, i.e. the array of interfaces it implements, is set at runtime with the creation of the proxy. Secondly, the dispatching mechanism of dynamic proxies allows, using polymorphism and reflection, for implementing generic behaviour independent of the targets’type.
As a strongly typed OO language, Java supports subtype polymorphism often referred to as simply polymorphism. In[7],subtype polymorphism is defined as the mechanism according to which variables of a given type can also hold objects of its subtype . Johnson and Foote [4] refer to a polymorphic procedure as an OO mechanism supporting reuse. Essentially. The invoke() methods of the proxies associated handlers can be seen as polymorphic procedures.
Inheritance is recognized as an OO mechanism that facilitates software reuse. Empirical studies have shown that, as OO systems develop in time, inheritance trees remain relatively shallow indicating that software developers are aware of the conflict between the advantages of inheritance and its disadvantages [8]. Advantage of inheritance are mainly reuse and disadvantage are increased coupling and complexity. In [9], Cargill recommends that developers should reduce inheritance and hence reduce coupling. Dynamic proxies can be employed to implement reusable code avoiding the problems of strong coupling of inheritance and aggregation.
Black-box implementation represents the traditional way of applying abstraction; that is, to separate implementation details and hide them behind component’s interface. This strategy of encapsulation promotes loose coupling, code reuse and also allows for reasoning about the correctness of components constituting the system [10,11]. We do not address the impact of customizing system behaviour at runtime on system correctness and leave this question for future investigation.
While the use of proxies is generally advantageous, there are limitations to employing proxies in a networking environment. HTTP Proxies must be properly installed before communication with legacy target systems can be established. Security constraints of firewalls could hamper the development within the corporate network. Benefits of caching proxies are constrained by several factors such as cache replacement policy, minimum document size cached and disk area allocated for cache.
Reflective model built on dynamic proxies
Dynamic proxies provide the means of constructing a reflection model. Reflection or meta-programming refers to the capability of a system to reason about and act upon itself. A reflective system provides a representation of its own behaviour. In addition to the representation of the underlying system it describes. The latter is often referred to as application domain or the real world, The self—representation is causally connected to that of the underlying system, meaning that changes made to self-representation are reflected in the underlying systems’ state and behaviour, and vice versa[12].
Objects, in conventional OOP, are representations of objects whose role is to observe and modify the objects they represent, i.e. their referents. Meta-computation is often performed by intercepting normal computation carried out by normal objects. Meta-objects trap actions of their referents, periorm meta-computation and thereby customize or substitute referents’ actions. Evidently, meta-objects themselves can also be represented by meta-meta-objects and so on. The resulting structure of the reflective system thus obtained is multi level and forms a reflective tower. Objects populating the base level are called base objects and objects residing at the higher levels are termed meta-objects. Base objects provide a representation of the application domain and thus perform computation on entities of this domain. Meta-objects perform computation on objects residing in the lower level.
In [13], Ferber classifies different model of reflection according to the relationship between meta-entities and base entities. We follow a reflective model based on the meta-object approach. In this model , each base-object has a potential meta-object associated with it. Our meta-object representation is, however, restricted to controlling the behaviour of referents and does not include their state. In[2], the authors propose a two-level reflective architecture supporting the meta-object approach to reflection(see Figure 4). The proposal is based on:
Figure 4. A two-level reflective architecture with dynamic proxies
Interpreting the invocation handler of dynamic proxies as meta-objects;
The causal relationship between meta-and base level(defined in terms of mechanisms associating a base-object to a proxy);
Events that trigger the meta-level being method calls on proxy objects. The events trigger the reification process in which a meta-object modifies the behaviour of its referent. In return, any changes made at the meta-level are reflected back on the reified elements at the base level.
We note that the proposed reflective model supports behavioural reflection[14]; it allows programs to intervene in the current execution in order to exercute some reflective code analyzing or modifying the course of events. It does not, however, support structural reflection. i.e. allow the program to alter its data structures statically fixed at compile time.
With a behavioural reflection model at hand, we could proceed and consider the Java language itself as a system application whose behaviour can be customized; Java class libraries could be modified in such a way to suit developers’ demand. This is in line with the meta-object protocols approach[15] base on the idea that we should and can ‘ open languages up’. In this context, the language design becomes part of the development process.
The meta-level architecture may be interpreted to support the approach of aspect-oriented programming [16], since it inherently exhibits a degree of separation of concerns; the application core concerns at the base level are separated from the non-functional concerns at the meta-level.
In[17], Biggerstaff discusses the reuse problem of scaling component libraries such as APIs and foundation class libraries. Extending reuse libraries in both component sizes and feature variations with acceptable performance leads to the combinatorial explosion problem, the feature combinatorics problem or the scaling problem. The key problem of reuse libraries is that they are based on static components with all coriesponding activity , such as composition,refinement and specialization being localized to predetermined areas of a target program, The solution to combinationrial explosion of the component library, according to Biggerstaff, is to build all feature variations into highly general components and leave component generation and composition decision until runtime. The open implementation approach due to Kizcales and followed in this paper provides a solution to the scaling problem.
原文正文(二)
SUMMARY
In object-oriented programming (OOP), proxies are entities that act as an intermediary between client objects and target objects. Dynamic proxies can be used to construct distributed systems that support the open implementation approach and promote code reuse. The OO paradigm supports code reuse through various ways including inheritance, polymorphism and aggregation. In this paper, we adopt a definition of software reuse restricted to reuse of code components and address the question of constructing distributed systems based on dynamic proxies. Different networking techniques and programming paradigms such as Java's Remote Method Invocation (RMI), the Common Object Request Broker Architecture (CORBA) and Java Servlets are used to implement the distributed client/server architecture. Copyright 2004 John Wiley & Sons, Ltd.
KEY WORDS: reusability; open implementation; distributed systems; proxy; meta-programming; reflection
THE SINGLE JVM IMPLEMENTATION
In earlier work [2], we presented some examples showing how dynamic proxies supported open implementation and code reuse. In this section, We review the example of transforming objects’attributes into active JavaBeans properties and highlight its practical use. Active JavaBeans properties are characterized by the firing of an event when the state of the object changes; for example, by invoking set methods. We can make a simple property active by binding its changes to anonymous event listeners. JavaBeans supports through a new event type called the PropertyChangeEvent, the listener interface PropertyChangeListener and through a support class called PropertyChangeSupport. The JavaBeans mechanism of active properties can be used for implementing the Model View Controller(MVC) pattern often employed in developing GUIs, The View object is supposed to be informed every time the state of its Model objects is changed. Views are registered as listeners to changes of active properties in corresponding Models. Implemented the mechanism of firing an even of change and thereby informing interested listeners can be implemented using dynamic proxies. The proxy implementation has several advantages when compared with the classical approach(using inheritance and aggregation) of realizing the MVC pattern for constructing GUIs, namely:
The separation of event firing and informing of listeners from basic classes(View and Models);
The provision of a generic implementation of the event-triggering mechanism.
[1] [2] [3] [4] [5] [6] [7] [8] [9] 下一页