(Reproduced) AOP: Programming to encapsulate and reuse of code aspect

xiaoxiao2021-03-06  211

AOP: Programming the package and reuse of code

Release Date: 4/8/2004

| Update Date: 5/28/2004

Dharma Shukla, Simon Fell, and Chris Sells

Level of Difficulty 1 2 3

Download this article: (538KB)

Abstract Aspect Programming (AOP) is a programming paradigm of Xerox Parc in the 1990s in the 1990s, which enables developers to better intertwine together. (Eg, math operation and abnormal processing) separation open. AOP methods have many advantages. First, the performance is improved due to more concise operation. Second, it allows the programmer to rewrite the same code less time. In summary, AOP can provide better encapsulation for different processes, and improve future interoperability.

What makes software engineers want themselves to be hardware engineers? Since the inventions of the function, the programmer spent a lot of time (most funds of its boss) to try to design such a system: they are all combined models, and the components created by others have constructed, arranged in a unique shape, and override Some pleasing colors. Everything in functions, templates, classes, components, etc. are all kinds of software engineers to create "software integrated circuits" (analog hardware designers).

I blame this on Lego (Lego toys). The pleasing clicks that have made two toy blocks (ie, components) are very addictive, which will prompt many programmers invented a new package and reuse new mechanism. The latest developments in this regard are called aspective programming (AOP). The core of the AOP is a way to arrange (one on the other) component, which can obtain a reuse level that other types of components cannot be obtained. This arrangement is done in the call stack between the client and the object, and the result is an object created a specific environment. This environment is what the AOP programmer is mainly pursued, continue to read this article, you will understand this.

The code example provided with this will be divided into two parts: COM section and the Microsoft .NET section. The COM section creates an infrastructure that can be added to the COM object, providing a user interface to configuring the class, and a sample implementation created on the infrastructure we provide is also given. The .NET section illustrates how to use the Built-in .NET infrastructure to complete the same task, but the code used is less, and more choices are more. Examples of examples of this infrastructure are also provided. All of this will be described later.

This page

What is face-oriented? Conventional Use AOP Design Frames As the aspect of the COM object Activation Aspect Builder.net Conclusion Binding Objects. Net Aspects and Context Conclusions Related Articles: For background information, see:

What is face-oriented?

In general, the object is "bonded" by a line of code. Create this object. Create that object. Set the properties for that object (its value to this object). There are also some user data. Stir it together. You can execute when you reach 450 degrees. This problem occurs in this manner in this manner: When you implement a different method, you need to spend a lot of time to write the same code. These code lines often have the following: Turn this method's activity record log to a file for debugging, run security check, start a transaction, open a database connection, remember to capture C exceptions or Win32 structured abnormalities Convert to COM exception, but also verify parameters. Moreover, it is necessary to remember the setting of the destruction of the method after the method is executed. This recurrent code often occurs because developers are trained to design the system based on the noun in the software press release. If you are designed, the Banking system, the Account class, and the Customer class must be essential, and they collect their unique details, but each method they need to perform logs, security checks, transaction management. The difference is that the log and other operations are some systems that are not related to specific applications. Everyone needs them. Everyone wrote these code. Everyone hates like this.

Oh, not everyone ... Everyone needs to use these services, everyone hates writes repeated code, but not everyone needs to write these code. For example, COM and .NET programmers can perform so-called property programming, also known as declarative programming. This technique allows programmers to modify types or methods with attributes, and declares that they need to run. For example, some services provided by COM include role-based security, real-time activation, distributed transaction management, and encapsulation processing. When a method is called, a set of objects obtained between clients and servers is placed (called "listener" for COM programmers, and is called "message reception" for .NET programmers.) Provide services for each method, without component developers write any code. This is a programming paradigm for aspect programming (in the 1990s Xerox, Gregor Kiczales in the Palo Alto Research Center, see http://www.parc.xerox.com/csl/groups/sda/publications/papers/ Kiczales-ecoop97 / for-web.pdf is the simplest form.

In the field of AOP, the COM listener is some aspects associated with components through metadata. Using metadata at runtime, it is usually performed when the object is created. When the client calls the method, those special aspects receive the process call, the opportunity to execute its service, and finally call the object. When returning, each aspect has the opportunity to expand. In this way, each method of each component can be extracted and put in various aspects in various aspects, allowing the runtime to place them. This group of works provides a context for the implementation of the component method. The context provides a method of implementation in the environment, with a special meaning.

Figure 1 is safely present in the context

For example, Figure 1 shows an object that is securely present in the context, which provides error propagation, transaction management, and synchronization. Programs in the Win32 console application can assume that there is a console in the context, and the result of calling the Printf will be displayed on the console, and the AOP object can also assume that the transaction has been established, and the database will be part of the transaction. If you have a problem with these services (for example, there is not enough resource to establish a transaction), the object will not be called, so there is no need to worry.

Back to top

General purpose AOP

Although Com provides most of the services required for AOP, to be used as a conventional use AOP environment, it still lacks a necessary important details: Define the ability to customize. For example, if the role-based security is not suitable, the role-based security (such as the most dangerous person protects its own object). If the programmer has this capability, many COM usual methods can be implemented with the AOP framework. Figure 2 provides an example short list. Back to top

Design framework

Of course, after this framework is thinking, we must also build it. We hope this framework has the following features:

• When the runtime between the client and the object is connected in series. • User-defined aspects are implemented in COM components. • What is the metadata description associated with each COM component, as the COM directory. • The client can be used to activate the components.

The concept of the AOP framework is simple. The key is to listen and delegate. The tip of the listener is to let the caller believe that the interface pointer it holds points to the object it requested, and actually this is a pointer to the listener, which can obtain the listener by one of the activation technologies described later later. . The listener needs to implement the same interface as the target component, but all calls need to be entrusted by stacking with the components. When the method is called, the listener will provide the opportunity to provide pre-processing and post-processing calls for each aspect, and the ability to disseminate or cancel the current call.

The AOP framework performs two different steps, components activation and method calls. In component activation, the AOP framework configuration implements the stack of the object and returns a list of listeners, not references to the actual object. In the method call, when the caller is called to the listener, the listener will call all registered aspects, thereby pre-processes the [IN] and [IN, OUT] parameters in the call stack, And provide the actual call to the object. Then return the value returned by the call returned by the transfer component, and the [IN, OUT] and [OUT] parameters on the stack are called, and the call is supplied to the aspect process.

Back to top

As a COM object

In our AOP framework, aspect is a COM class of an IASPECT interface, as shown in Figure 3. The frame will call all specified IASPECT :: Preprocess methods before passing the method call to the actual underlying component instance (hereinafter referred to as the envelope). It passes the IID, method name, method of the client, and the VTBL slot, method, method of the method, and the enumerator of the [IN] and [IN, OUT] parameters to the corresponding aspect. If the region returns a fault HRESULT from PreProcess, the framework does not provide calls to the applause, actually canceling the call.

Aspects are successfully returned, and the framework provides the actual call to the applare. Regardless of whether it returns hRESULT from the client, the framework calls the IASPECT: PostProcess method, passes all the parameters required by the HRESULT and PostProcess methods returned by the client, only this time the enumerator is built in [OUT], [IN, OUT] and [OUT, RETVAL] parameters.

Figure 4 shows how to write a call tracking, which can track the parameters provided by all the caller passing to the entrusser method.

Since there is already a framework for calling and one can be used, we need a mechanism to connect them in series. This operation is performed when an object is activated.

Back to top

Object activation

Although we have to stack any number of clients and objects, the client should could create objects and call their methods, just as there is no way to listen. Worse, CoM If you don't take some strange technical means (this is the Microsoft Transaction Service must be implemented before integrated into the COM infrastructure), it is not possible to support any of its main activation API CocreateInstance. Scalability code. However, COM does provide a fully extended activation API: Visual Basic's getObject (for C programmers is CogetherObject). We use custom name objects to build AOP activation code based on this API. The COM name object is a piece of code that converts any string (called display name) into a COM object, which means you can create a new one, or find one from the file, even download it from the moon. Our AOP name object obtains metadata (describes the aspects associated with the class associated with the class here), create the instance of such a class, the constructor stack, connect them together through the AOP listener, then return the listener to give Client. Here is an example:

Private sub flow_load ()

Set myfoo = getObject ("AOACTIVATOR: C: /AOPFOO.XML")

Myfoo.DOSMETHINGFOOISH

End Sub

Note that in addition to get an instance of the FOO, the client uses components without any special operations. Although the aopfoo.xml file associates any number of aspects with the particular instance of the FOO, it still implements the same interface, more importantly, it has the same semantic.

Implementing Custom COM name objects in a certain sense is a magical technology, mainly involving insider knowledge of the OLE details. Fortunately, most of the content achieved is a word, and the COM community has written the basic implementation of the name object for a long time ago, in the ATL class called CCOMMONIKER. (You can access http://www.sellsbrothers.com/tools to get the COM name object framework.) Use this framework, we really need to care about implementing ParsedisPlayName (this is a boring method for analytical custom display name syntax) and bindtoobject (Part of the name object, the name object is used to activate the COM object indicated by the display name provided by the client) (see Figure 5).

Please note that the code in Figure 5 does not show the most difficult part - the creation and initialization of the listener. The reason is difficult, not in the listener itself, but the work that the listener must do. Keep in mind that the General AOP framework wants to play a function of genericity, and must be able to respond to QueryInterFace methods with a set of interfaces that are identical to any component packaged. The returned interface must be able to obtain the call stack provided by the client of each method, pass it to all aspects, and transferred to the component itself, keep the parameters complete - no matter how much, and what type. This is a very difficult task involving a large number of __declspec (name) and ASM Thunk.

Fortunately, because the COM community is already very mature, we have to stand on the shoulders of the giant using the General Brown (UD), a COM component that is created by the KEITH BROWN. Keith has written its UD in the MSJ in MSJ, and the article is "Building A Lightweight Com Interception Framework, Part i: The Universal DeleGator", and Part II: "The Guts of To". We use keith's UD to implement the AOP framework, which reduces the "magic" part of the BindToObject implementation, as shown in Figure 6. In order to package the target component for the client, do the following four steps:

1. Create an actual component using the CLSID of the component, which is passed to the original object in the metadata XML file.

2. Create a DelegaTromOok object, listen to the QueryInterface call to the object. The hook is responsible for calling the way to each other.

3. Next, create a UD object and retrieve the IDELEGATORFACTORY interface.

4. Use the IDELEGATORFACTORY to call CREATEDELEGATOR, pass the interface of the actual object, the IIDRESULT of the instructor, and the interface of the source call, and the pointer to the interface pointer. The delegate returns a pointer to the listener, which can call each called delegator hook.

Figure 7 COM AOP structure

The result is shown in Figure 7. From this, the client can use the listener as the actual interface pointer of the target component. After the call, they route them to the target components along the aspects of the path.

Back to top

Aspect builder

In order to activate the components and make all aspects of the correct series, our AOP name object rely on an XML file to describe components and associated aspects. The format is very simple, only contains only the CLSID and aspect components of the component. The example of Figure 8 packs Microsoft FlexGrid Control with two aspects. To simplify the creation task of the AOP metadata instance, we created aspect builder (shown in Figure 9).

Figure 9 Aspect Builder

Aspect Builder will enumerate all aspects of the machine, and display them with a cloud image in the list view on the left. The ASPECT Builder's client area contains graphical representation of the component. You can double-click it (or use the corresponding menu item) and specify the PROGID of the component. Once a component is selected, you can drag and drop aspects into the client area, and add aspects to the AOP metadata of the component.

To generate the XML format required to provide the AOP name object, you can select the "Compile" menu item in the "Tools" menu, and metadata will appear in the bottom pane. You can actually write scripts in the Verify Aspects pane, and the verification metadata is indeed correct. You can save your XML instance on the disk or you can overload them with Aspect Builder.

Back to top

Aspects in .NET

Although Aspect Builder is greatly simplified, it is not convenient to perform AOP programming in COM because of the storage of the components. Worse, COM's metadata lacks many necessary features in scalability, which is why we feel that the metadata and classes are stored. However, as a obvious successor, .NET has no such problem. The metadata of .NET is fully scalable, so all necessary foundations can be associated with the class itself directly through the attributes. For example, give a custom .NET property, we can easily associate the call trace attribute with the .NET method: public class bar {

[CallTracingAttribute ("in bar ctor")]]]

Public bar () {}

[CallTracingAttribute ("in bar.calculate method"]]]]

Public int Calculate (int x, int y) {return x y;}

}

Note that the string output when CallTraacingAttribute and the access method are included in square brackets. This is the attribute syntax associated with the two methods of the custom metadata and BAR. Like the AOP framework in COM, the attributes in .NET are classified according to the components in the .NET. Custom attributes in .NET are implemented with class that is derived from Attribute, as shown below:

Using system;

Using system.reflection;

[AttributeUSAGE (AttributeTargets.classmembers,

Allowmultiple = false)]]

Public Class CallTracingAttribute: attribute {

Public calltracingAttribute (string s) {

Console.WriteLine (s);

}

}

Our attribute class itself also has attributes, which modifies its behavior. In this case, we require this attribute only with the method, not the assembly, class, or field association, and each method can only have one trace attribute and association.

After the attribute is associated with the method, we have successfully half. In order to provide AOP function, it is also necessary to establish a front and rear access call stack for the environment necessary for each method to establish the environment. This requires a listener, and the context of the component dependent. In COM, we asked the client to use the AOP name object activation component to implement this task. Fortunately, .NET has been built into, so there is no special job without any special work.

Back to top

Context binding object

The key to listening in .NET (like COM) is that the context is provided for the COM component. In a COM and a custom AOP framework, the context is provided by setting the context to the component to establish the context of the component before the method is executed in the method execution. In .NET, the context will be provided for any class derived from System.ContextBoundObject:

Public Class LikeToliVealone: ​​contextBoundObject {...}

When the instance of the LikeTolivealone class is activated, the .NET runtime will automatically create a separate context for its survival, and build a listener, which can happen from our own aspects. .NET listener is a combination of two objects - transparent agent and real agents. The behavior of the transparent agent is the same as the target object. Like the COM AOP listener, it will call the stack sequence into a object called a message, and then pass the message to the real agent. The real agent receives the message and sends it to the first message reception. The first message receives the message for pre-processing, continues to send it to the next message received in the message receiving stack located between the client and the object, and then processes the message. The next message receives this, so that it is pushed until the stack builder is reached, it will call the message deserved callback, call the object, serialize outbound parameters, and return values, and return to the previous message. This calling chain is shown in Figure 10. Figure 10 listening

In order to participate in this message receiving chain, we first need to derive attributes from ContextAttribute, and provide so-called context properties, updating the property to participate in context binding objects:

{[AttributeUSAGE (AttributeTargets.class)]

Public Class CallTracingAttribute: ContextAttribute {

Public CallTracingAttribute ():

Base ("CallTrace") {}

Public Override Void

GetPropertiesFornewContext

(IconstructionCallMessage CCM) {

CCM.ContextProperties.Add (New

CallTracingProperty ());

}

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

}

When this object is activated, the getPropertiesForNewContext method is called for each context property. This way we can add your context properties to the list of properties associated with the new context created for objects. Context properties allow us to associate messages associated with objects in the message receiving chain. The property class receives the factories received by IconTExtObject and IconTextObjectSink as aspects:

Public Class CallTracingProperty: iconTextProperty,

IcontributeObjectsink {

Public IMESSAGESINK GETOBJECTSINK (MarshalByrefObject O,

IMessagesink Next) {

Return New CallTracingAnspect (next);

}

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

}

The proxy creation property is shown in Figure 11, which first creates a context property, and then creates a message to receive.

Figure 11. Creation of Net Messagesink

Back to top

.NET

When everything is attached correctly, each call will enter the IMESSAGESIN implementation. SyncProcessMessage allows us to preprocess and post processing messages, as shown in Figure 12. Finally, I hope to use CallTracingAttribute to declare its preference with the context binding class associated with the call tracking.

Finally, I hope to use CallTracingAttribute to declare its preference with the context binding class associated with the call tracking.

{[Aop.experiments.calltraacingattribute ()]

Public class traceme: contextBoundObject {

Public int ReturnFive (String s) {Return 5;

}

}

Please note that we associate the context attributes and classes without each method. The .NET context structure will automatically notify us of each method, so our call tracking property has all the information you need, which avoids trouble with each method and each method when it avoids the previous processing of normal properties. Aspect is activated when the client class instantiates classes and calls a method:

Public class client {

Public static void main () {

TRACEME TRACEME = New Traceme ();

Traceme.ReturnFive ("stringarg");

}

}

Output, client and direction-oriented object output:

PreProcessing: Traceme.ReturnFive (S = Stringarg)

PostProcessing: Traceme.ReturnFive (Returned [5])

Back to top

Aspect and context

So far, our simple aspect has not really realized the expected AOP ideal. Although it is indeed a separate pretreatment and post-treatment of method calls, it is really interesting to implement its own impact on the method. For example, COM transactionity will enable all resource providers used in the object method to participate in the same transaction, so that all activities can be suspended only by suspended COM transaction. To this end, COM has increased the COM call context, which provides aggregation points for all components of interested access to current transactions. Similarly, .NET also provides scalable call contexts that can be used to allow methods to participate. For example, you can add information (it packages in call tracking aspect) by placing itself in the .NET context, can add information in the tracking message stream, as follows:

INTERNAL CLASS CALLTRACINGASPECT: IMESSAGESINK {

Public static string contextName {

Get {return "calltrace";

}

Private void preprocess (iMessage MSG) {

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

// set US Up in The Call Context

Call.LogicalCallContext.SetData (ContextName, this);

}

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

}

Once the aspect is added to the call context, the method can take it again and participate in tracking:

[CALLTRACINGATTRIBUTE ()]

Public class traceme: contextBoundObject {

Public int ReturnFive (String s) {

Object obj =

CallContext.getdata (CALLTRACINGASPECT.CONTEXTNAME);

CallTracingAmect aspect = (calltracingaspect) OBJ;

Aspect.trace ("Inside MethodCall");

Return 5;

}

By providing a way to increase the call context, .NET allows you to set a true environment for objects. In our example, the object is allowed to add a tracking statement to the stream, without having to know the destination of the stream, how to build a stream and when the stream is destroyed, which is like COM transactionality, as shown below:

PreProcessing: Traceme.ReturnFive (S = Stringarg)

During: traceme.returnfive: Inside methodcallpostprocessing: traceme.returnfive (returned [5])

Back to top

in conclusion

With facing aspects, developers can use the same way as the package assembly itself across components. By using metadata and listeners, any service can be placed between clients and objects, which is seamless in COM, seamless in .NET. Aspects described herein can access the calling stack during the invoking process call, which provides an increased context for survival. Although AOP is not yet mature than structured or object-oriented programming, the local support of AOP is a valuable tool for our pursuit of software dreams like Lego toys.

Back to top

Related Articles, please refer to:

KEITH Brown's series of articles about universal commission:

Building a Lightweight COM Interception Framework, Part 1: The Universal Delegator

BUILDING A LIGHTWEIGHT COM Interception Framework, Part II: The Guts of The Ud

Back to top

For background information, see:

http://portal.acm.org/portal.cfm

http://www.aosd.net

GENERATIVE PROGRAMING (Addison-Wesley, 2000) written in Krzysztof Czarnecki and Ulrich Eisnecker (Addison-Wesley, 2000)

AspectJ-a Java Implementation of AOP

Dharma Shukla is a leader of the Microsoft's BizTalk Server group. Dharma is currently engaged in the development of next-generation enterprise tools. You can send an email to Dharmas@microsoft.com and contact him.

Simon Fell is an outstanding engineer of Provada, developing a distributed system using XML, .NET and COM. Simon is the author of the PocketSoap Open Source Soap Toolkit and creates COM TRACEHOOK with Chris Sells, currently engaged in the development of SOAP binding of Avian Carrier. To contact Simon, you can send an email to http://www.pocketsoap.com.

Chris Sells is an independent consultant, specialized in distributed applications in .NET and COM, and teaches in Developmentors. He created several books, including ATL INTERNALs, this book should be updated this year. He is writing a book in a Windows form and will be published in 2002. You can send an email to http://www.sellsbrothers.com contact chris.

Puck from MSDN Magazine in March 2002.

This magazine can be purchased through all local newsstands or subscribe here.

Go to the original English page

转载请注明原文地址:https://www.9cbs.com/read-128876.html

New Post(0)