/**
Author: willpower
Source: rifoo Technology (http://www.rifoo.com)
Time: 2006-03-06
Remarks: Reprinted please keep the above statement
**/
In the previous section, we completed an audit service to help us track program changes. Now, we will add this service to our code and configure it in our experiment.
So how do we do it?
The interceptor policy uses three objects: the target (here our facade), the proxy object created by spring for us, and an interceptor created by ourselves ). We have to do three things:
Glossary:
Advice: How to declare before notification, afterreturning notification, and afterthrowing notification as bean.
Pointcut: describes how to declare the static pointcut logic to link all content in the XML spring bean configuration file.
Advisor: the method of associating the entry point definition with the notification bean.
1. Configure the notification object
2. Configure the advisor object, including the target object, target method, and notification object.
3. Configure the target object)
4. Configure the proxy object using this advise
The target object already exists: it is the facade class we have previously completed. The proxy object also exists because we use it to complete the transaction. Therefore, we only need to configure the notification object and add it to our proxy. See the following sample code:
Example 6-3. RentABike-servlet.xml
<Beans>
<Bean id = "transactionmanager"
Class = "org. springframework. Orm. hibernate. hibernatetransactionmanager">
<Property name = "sessionfactory">
<Ref local = "sessionfactory"/>
</Property>
</Bean>
<Bean id = "transactioninterceptor"
Class = "org. springframework. transaction. Interceptor. transactioninterceptor">
<Property name = "transactionmanager">
<Ref local = "transactionmanager"/>
</Property>
<Property name = "transactionattributesource">
<Value>
Com. Springbook. hibernaterentabike. Save * = propagation_required
</Value>
</Property>
</Bean>
<Bean id = "loggingbeforeinterceptor"
Class = "com. Springbook. interceptors. loggingbefore">
<Property name = "Factory">
<Ref local = "sessionfactory"/>
</Property>
</Bean>
<Bean id = "rentabiketarget" class = "com. Springbook. hibateabike">
<Property name = "storename">
<Value> Bruce's bikes </value>
</Property>
<Property name = "sessionfactory">
<Ref local = "sessionfactory"/>
</Property>
</Bean>
<Bean id = "rentabike"
Class = "org. springframework. AOP. Framework. proxyfactorybean">
<Property name = "proxyinterfaces">
<Value> com. Springbook. rentabike </value>
</Property>
<Property name = "interceptornames">
<List>
<Value> loggingbeforeinterceptor </value>
<Value> transactioninterceptor </value>
<Value> rentabiketarget </value>
</List>
</Property>
</Bean>
<! -- Etc. -->
</Beans>
<Bean id = "datasource" class = "org. springframework. JDBC. datasource. drivermanagerdatasource">
<Property name = "driverclassname">
<Value> com. MySQL. JDBC. Driver </value>
</Property>
<Property name = "url">
<Value> JDBC: mysql: // localhost/bikestore </value>
</Property>
<Property name = "username"> <value> bikestore </value> </property>
</Bean>
The simple before advice is used in this example. Now let's take a look at the most complex around advice. If we can understand the most advanced process, everything else will become simple. Tell us how advice works in spring. Bikedao is a target object ). It has a lot of business code. To configure an interceptor, We need to specify a proxy here ). This agent is responsible for maintaining a string of interceptors (that is, the interceptor chain ). An object uses a proxy to call a method rather than a target object. When we call a method on the proxy or cause an exception, the proxy object calls the first interceptor in the interceptor chain. Each interceptor will do their own work and wake up the next interceptor. The last interceptor will call the method or exception of the target object .. After the target object is called, the interceptor only returns the result.
In this example, we configure a proxy on the target object and tell the proxy to apply our interceptor to all methods of the target object. However, we can only use regular expressions to specify a subset of a method. The following is the interceptor code:
Example 6-4. loggingaround. Java
Public class loggingaround implements methodinterceptor {
Private sessionfactory factory;
Public sessionfactory getfactory (){
Return factory;
}
Public void setfactory (sessionfactory factory ){
This. Factory = factory;
}
Private void logevent (string methodname, string message)
Throws exception {
Session S = NULL;
Logevent Le = new logevent (methodname, new date (), message );
Try {
S = factory. opensession ();
S. Save (LE );
} Catch (exception ex ){
// Log the exception
} Finally {
S. Close ();
}
}
Public object invoke (methodinvocation)
Throws throwable {
Logevent (methodinvocation. getmethod (). getname (), "entering call .");
Object result = methodinvocation. Proceed ();
Logevent (methodinvocation. getmethod (). getname (), "leaving call .");
Return result;
}
}
Display the new configuration file:
Example 6-5. RentABike-servlet.xml
<Bean id = "loggingaround" class = "com. Springbook. interceptors. loggingaround">
<Property name = "Factory"> <ref local = "sessionfactory"/> </property>
</Bean>
<Bean id = "saveadvisor" class = "org. springframework. AOP. Support. regexpmethodpointcutadvisor">
<Property name = "advice">
<Ref local = "loggingaround"/>
</Property>
<Property name = "patterns">
<List>
<Value>. * Save. * </value>
</List>
</Property>
</Bean>
<Bean id = "rentabiketarget" class = "com. Springbook. hibateabike">
<Property name = "storename"> <value> Bruce's bikes </value> </property>
<Property name = "sessionfactory"> <ref local = "sessionfactory"/> </property>
</Bean>
<Bean id = "rentabike"
Class = "org. springframework. AOP. Framework. proxyfactorybean">
<Property name = "proxyinterfaces">
<Value> com. Springbook. rentabike </value>
</Property>
<Property name = "interceptornames">
<List>
<Value> transactioninterceptor </value>
<Value> saveadvisor </value>
<Value> rentabiketarget </value>
</List>
</Property>
</Bean>
The following table shows the results after before and after advice are called only by the Save method.
Example 6-6. Examining the contents of the logging table
+ --------- + -------------- + ------------ + ---------------- +
| Eventid | methodname | datetime | message |
+ --------- + -------------- + ------------ + ---------------- +
| 14 | savebike | 2004-10-13 | entering call. |
| 15 | savebike | 2004-10-13 | leaving call. |
| 16 | savecustomer | 2004-10-13 | entering call. |
| 17 | savecustomer | 2004-10-13 | leaving call. |
| 18 | savebike | 2004-10-13 | entering call. |
| 19 | savebike | 2004-10-13 | leaving call. |
+ --------- + -------------- + ------------ + ---------------- +
The final result is indeed what we want. Advice is triggered every time a specified method calls the target object. We have completed this declarative audit function (declarative auditing ). In fact, we can write any service and make it declarative.