AOP: Aspect-Oriented Programming.
My understanding is: for multiple instance objects, place their codes together, cut a knife into one or more specific positions, and perform some unified operations on the positions of this section.
The most common scenario of AOP is log.
In general, we want to record logs before and after some function calls. The easiest way to think of is as follows:Package COM. red. myaop. bean; <br/> public class easylog {<br/>/** <br/> * @ Param ARGs <br/> */<br/> Public static void main (string [] ARGs) {<br/> easylog easy = new easylog (); </P> <p> system. out. println ("do before... "); <br/> easy. say (); <br/> system. out. println ("do after... "); <br/>}</P> <p> Public void say () {</P> <p> system. out. println ("hello"); </P> <p >}< br/>}
Add the log information before and after each function call.
However, if you want to log all objects by calling the say () function, the following will occur if you use this method:..... <Br/> system. out. println ("do before... "); <br/> easy. say (); <br/> system. out. println ("do after... "); <br/> system. out. println ("do before... "); <br/> easy1.say (); <br/> system. out. println ("do after... "); <br/> system. out. println ("do before... "); <br/> easy2.say (); <br/> system. out. println ("do after... "); <br/> ......
This creates a cross-section requirement, that is, I want to cut all objects into the say function and make some logs on this section.
Currently, Java's dynamic proxy method is used to proxy function calls. You can log the actual calls in proxy function calls.
Assume that an interface declares the function say:
Package com. Red. myaop. Bean; <br/> Public interface Isay {<br/> Public void say (); <br/>}
There are two classes that implement this interface:
Package COM. red. myaop. bean; <br/> public class Hello implements Isay {<br/> @ override <br/> Public void say () {<br/> system. out. println ("Hello! "); <Br/>}< br/>}
Package COM. red. myaop. bean; <br/> public class Bye implements Isay {<br/> @ override <br/> Public void say () {<br/> system. out. println ("Bye bye! "); <Br/>}< br/>}
I hope the instances of these two classes can make logs before and after the say call.
Some programming interfaces in Java reflection can be used.
The core method is to call
Object
Java. Lang. Reflect. Proxy
. Newproxyinstance (classloader
Loader, Class
<?> []
Interfaces, invocationhandler
H) throws illegalargumentexception
It is a static method and requires a class loader, interface, and a proxy instance implementing invocationhandler. A corresponding proxy class is returned.
The first parameter indicates the class loader of the object to be proxy. Here it refers to the hello and bye class loaders, and the second parameter indicates the interface of the proxy class, isay. The last parameter is a proxy instance that implements invocationhandler.
Object
Invoke (Object
Proxy, Method
Method, Object
[]
Arg2) throws throwable
.
Here, proxy is the proxy itself (this can be understood for the time being, but actually there is a difference ). Method is the currently called function of the proxy object. arg2 is the parameter of the called function.
This is what I want to do. Generally, a new instance object is generated, for example, Isay H = new Hello. when you say (), the function is called directly. Now I want to hijack this object so that the function call can be customized. Here, it adds logs before and after the say call.
How to hijack this object is to create a proxy for this object. When you want to call the say method, delegate this proxy object to call the actual say method, the proxy can perform some actions when actually calling the say method.
The implementation method is as follows:
Package COM. red. myaop. proxy; <br/> Import Java. lang. reflect. invocationhandler; <br/> Import Java. lang. reflect. method; <br/> public class myproxy implements invocationhandler {<br/> private object delegate; </P> <p> Public object getdelegate () {<br/> return delegate; <br/>}< br/> Public void setdelegate (Object delegate) {<br/> This. delegate = delegate; <br/>}< br/> @ override <br/> Public object invoke (Object proxy, method, object [] arg2) <br/> throws throwable {</P> <p> system. out. println ("do before... "); <br/> Object ret = method. invoke (this. delegate, arg2); <br/> system. out. println ("do after... "); <br/> return ret; <br/>}< br/>
This is a function call proxy class. First, it implements the invoke method. Secondly, he has a delegate member whose type is object, that is, myproxy can be the function call proxy of any object, that is, he can hijack any class object, the invoke method is automatically called when a function of the hijacked object is called. You can customize how the method of the hijacked object is called in this method, some logs are printed before and after the hijacked function is called.
Package COM. red. myaop. proxy; <br/> Import Java. lang. reflect. proxy; <br/> public class proxyfactory {<br/> Public static object getinstance (class clazz) {<br/> myproxy proxy = new myproxy (); <br/> try {<br/> proxy. setdelegate (clazz. newinstance (); <br/>} catch (instantiationexception e) {<br/> E. printstacktrace (); <br/>} catch (illegalaccessexception e) {<br/> E. printstacktrace (); <br/>}< br/> return proxy. newproxyinstance (clazz. getclassloader (), clazz. getinterfaces (), proxy); <br/>}< br/>}
This is a factory class with only one static method. It accepts a class-type parameter and returns a proxy object of this class, that is, this class object has been hijacked, and the returned is this hijacking, however, it does not seem to have any special appearance. Its Class Loader is the same as the original one, and its Implemented interfaces are the same as the original one. In getinstance, the instance is first created based on the class, which has the same effect as new. Then, the myproxy instance is used as its function call proxy, that is, any function call to this object must be processed by proxy. Finally, return the proxy object generated using the proxy. newproxyinstance method.
The main function of the test is as follows:
Package COM. red. myaop. bean; <br/> Import COM. red. myaop. proxy. proxyfactory; <br/> public class tester {<br/> Public static void main (string [] ARGs) {</P> <p> Isay Hello = (Isay) proxyfactory. getinstance (hello. class); <br/> Isay byE = (Isay) proxyfactory. getinstance (bye. class); </P> <p> hello. say (); <br/> bye. say (); </P> <p >}< br/>}
It can be seen that the objects generated with proxyfactory are no different from those generated with new, but they are actually hijacked, so the running result is:
Do before...
Hello!
Do after...
Do before...
Bye bye!
Do after...
However, the j2se standard interface only provides a dynamic proxy for the classes that implement the interface. Therefore, the proxy class must implement an interface. Otherwise, it cannot proxy a function. If you want to perform dynamic proxy for common classes, we will not discuss it here.