Reprinted from Concurrent Programming network –ifeve.com
Content index
Create an agent
Invocationhandler interface
Common use Cases
- Database Connectivity and Things management
- Dynamic mock objects in unit tests
- Adapters between custom factories and dependency injection (DI) containers
- AOP-like method interceptors
Using the Java reflection mechanism, you can dynamically create an implementation of an interface at run time. The Java.lang.reflect.Proxy class can implement this function. The name of this class (translator Note: Proxy is the agent) is why the dynamic interface implementation is called the dynamic agent. Dynamic proxies are used extensively, such as database connectivity and object management (transaction management), dynamic mock objects used in unit testing, and method interception in AOP, among others.
Create an agent
You can create dynamic proxies by using the Proxy.newproxyinstance () method. The Newproxyinstance () method has three parameters:
1. Class loader (ClassLoader) is used to load dynamic proxy classes.
2. An array of interfaces to implement.
3, a Invocationhandler the invocation of all methods to the proxy.
The following example:
New= (myinterface) proxy.newproxyinstance ( myinterface. class . getClassLoader (), New Class[] {myinterface. Class }, handler);
After executing this code, the variable proxy contains a dynamic implementation of a MyInterface interface. All calls to proxy are shifted to the handler that implement the Invocationhandler interface. The contents of the Invocationhandler will be described in the next paragraph.
Invocationhandler interface
As mentioned earlier, when you call the Proxy.newproxyinstance () method, you have to pass in an implementation of the Invocationhandler interface. All method calls to the dynamic proxy object are shifted to the implementation of the Invocationhandler interface, and the following is the definition of the Invocationhandler interface:
Public Interface invocationhandler{ Object Invoke (Object proxy, Method method, object[] args) throws Throwable;}
Here is the definition of its implementation class:
Public class Implements invocationhandler{ public object Invoke (Object proxy, Method method, object[] args) c14/>throws throwable { //dosomething "dynamic" }}
The proxy parameter in the incoming invoke () method is a dynamic proxy object that implements the interface to be proxied. Usually you don't need him.
The method object parameters in the Invoke () method represent the methods to be called in the interface of the dynamic proxy, from which you can obtain information such as the name of the method, the parameters of the method, the type of the parameter, and so on. You can refer to the previous article about method in this section.
The object array parameter contains the method parameters that are required by the method of the dynamic proxy. Note: Native data types (such as int,long, etc.) method parameters pass in an equivalent wrapper object (such as Integer, Long, and so on).
Common use Cases
Dynamic proxies are often applied in the following situations
- Database Connectivity and Things management
- Dynamic mock objects in unit tests
- Adapters between custom factories and dependency injection (DI) containers
- AOP-like method interceptors
Database Connectivity and Things management
There is a thing agent in the spring framework that allows you to commit/rollback a thing. Its specific principles are described in detail in advanced Connection and Transaction demarcation and propagation, so here I'll briefly describe the sequence of method calls as follows:
Web controller ---Proxy.execute (...); --Connection.setautocommit (false) ; --Realaction.execute (); Realaction does database work---connection.commit ();
Dynamic mock objects in unit tests
The Butterfly testing tool uses dynamic proxies to dynamically implement the stub, mock, and proxy classes for unit testing. When testing Class A, if you use interface B, you can pass a mock to a B interface instead of the actual B interface implementation. All method calls to interface B are logged, and you can set the return value of the method in the mock of B yourself.
And the Butterfly Testing tool allows you to wrap a real B-interface implementation in a mock of B, so that all methods that call the mock are recorded, and then the call is turned to the real B-interface implementation. This allows you to check the invocation of the actual function of the method in B. For example, when you test DAO you can wrap a real database connection into a mock. In this case, as is true, DAO can read and write data in the database, and the mock will pass the read and write instructions to the database to the database, and you can use the mock to check that the DAO is using the database connection in the correct way. For example, you can check if the Connection.close () method is called. This situation cannot be judged simply by invoking the return value of the DAO method.
Adapters between custom factories and dependency injection (DI) containers
Dependency Injection container Butterfly container has a very powerful feature that allows you to inject the entire container into the bean generated by the container. However, if you do not want to rely on the interface of this container, this container can be adapted to your own defined factory interface. You just need this interface rather than the implementation of the interface, so this factory interface and your class look like this:
Public Interfaceimyfactory {Bean bean1 (); person person (); ...} Public classmyaction{protectedImyfactory myfactory=NULL; Publicmyaction (Imyfactory factory) { This. MyFactory =Factory; } Public voidexecute () {Bean Bean= This. Myfactory.bean (); Person Person= This. Myfactory.person (); }}
This method call actually calls the Icontainer.instance () method when the Myaction class invokes a method that is injected through a container into a imyfactory instance of the constructor method, which allows you to get an instance from the container. This way the object can use the Butterfly container container as a factory at run time, which is obviously better than injecting it when creating the class. And this method does not depend on any interface in the Butterfly container.
AOP-like method interceptors
The spring framework can intercept the method calls of the specified bean, and you only need to provide the interface that the bean inherits from. Spring uses dynamic proxies to wrap beans. All calls to methods in the bean are intercepted by the proxy. The agent can determine whether to call other methods or invoke methods of other objects before invoking the actual method, and to invoke other proxy methods after the bean's method call is complete.
Original address Author: Jakob Jenkov Translator: Yevenhai ([email protected])
Java Reflection (11): Dynamic Proxy