One, definition: Agent mode (proxy): Provides a proxy for other objects to control access to this object.
Second, its class diagram:
Third, classification one: static agent
1, Introduction: That is, we need to write a proxy object for the target object, generated at compile time this proxy object, and then through the access to this agent, to achieve certain functions of the target object.
2, simple application: Here we look at a simple login log out example:
Interface for logon functions:
/**
* Public interface, target objects and agents to achieve *
* * *
interface ilogin{
//Login
void login ();
Log out
void logout ();
}
Target interface for implementation:
/**
* target object, realize common interface, achieve login logout function/public
class Reallogin implements ilogin{publicly
void login () {
try {
thread.sleep (3200);
} catch (Interruptedexception e) {
e.printstacktrace ();
}
SYSTEM.OUT.PRINTLN ("Login system ...");
public void Logout () {
try {
thread.sleep (2200);
} catch (Interruptedexception e) {
E.printstacktrace ();
}
System.out.println ("Exit system ...");
}
As you can see, we're adding thread sleep to the above method, because I want to test the login log time through the proxy mode, because the Java program follows the OCP (open to extended, closed to modify) principle, so in order not to modify the original code, we use the static proxy mode:
Code for Proxy (proxy object):
/**
* Proxy object, Proxy target object Reallogin
/public class Proxylogin implements ilogin{
//This class contains the target object
private Reallogin Target;
Construction method Public
Proxylogin (reallogin target) {
this.target = target;
}
@Override public
void Login () {
//start time
long begin = System.currenttimemillis ();
Target.login ();
Ending Time
long end = System.currenttimemillis ();
System.out.println ("time-consuming" + (End-begin) + "millisecond");
}
@Override public
void Logout () {
Long begin = System.currenttimemillis ();
Target.logout ();
Long end = System.currenttimemillis ();
System.out.println ("time-consuming" + (End-begin) + "milliseconds");
}
Good, through the proxy mode, very simple to achieve the login log out of time capture, but, if the customer suddenly asked us to all the class method of time to capture, then what to do? You can't always write a proxy class for every class, it's too much trouble. What's the matter?
3, Analysis: Here are examples and extensions let's take a look at the drawbacks of the static proxy model:
A, if the above demand, then there is bound to be the result of class explosion;
b, of course, the code to capture the execution time of the method is the same, we write each method, each class is written, this is the code duplication, does not achieve the effect of code reuse, which is completely contrary to the principle of object-oriented design.
4, think: Prevent the occurrence of class explosion, so that the code can be reused. Can we use a proxy class to broker all the required calculation methods to run the time ... Look at the dynamic proxy mode below.
Four, dynamic agent
1, introduce: Through the reflection mechanism, using the proxy class provided by JDK, when the program runs in memory according to target object to create proxy object, avoid the appearance of class explosion. The Proxy method writes only one so that the code is reused.
2, solve the above problem:
A, the preparation of the Proxy method:
/**
* This class needs to implement the Invocationhandler interface
* Calling the processor, and when the proxy object invokes the proxy method, the Invoke method registered in the calling processor is invoked automatically.
* * Public
class Timerinvocationhandler implements Invocationhandler {
//target object, get private by reflection mechanism
Object Target;
Construct method Public
Timerinvocationhandler (Object target) {
this.target = target;
}
/**
* parameter:
* Object Proxy: Reference to proxy objects, memory address of the proxy object in the proxy variable (this parameter is rarely used) Method: The target approach of the target object.
* Object[] args: The argument required when the target method of the target object executes.
* *
@Override Public
object Invoke (Object Proxy, Method method, object[] args) throws Throwable {
// Start time
long begin = System.currenttimemillis ();
Executes the method object in the target object
RetValue = Method.invoke (target, args);
Ending Time
long end = System.currenttimemillis ();
Calculation time
System.out.println ("time-consuming" + (End-begin) + "millisecond");
Return RetValue
}
}
b, note the writing of the test procedures here:
/**
* Note: The JDK built-in dynamic proxy proxy can only proxy interface
* (if you want both the proxy interface and the proxy abstract class to use a third party component: for example, cglib)/public
class Test {
public static void Main (string[] args) {
//Create object
ilogin target = new Proxylogin ();
Create proxy object: Java.lang.reflect.Proxy completes the dynamic creation//parameter of proxy object through the dynamic proxy class built by JDK
:
ClassLoader loader;
The class loader here is primarily used to load the temporary bytecode generated in memory, and the
class loader of the proxy class needs to be consistent with the class loader of the target class.
class[] interfaces;
The proxy class and the target class must implement the "Same" interface. (A class can implement multiple interfaces at the same time)
Invocationhandler handler;
When the proxy object invokes the proxy method, the Invoke method "registered" in the calling processor is invoked automatically.
Ilogin proxy = (iuserservice) proxy.newproxyinstance (Target.getclass (). getClassLoader (), New class[]{ Iuserservice.class},new Timerinvocationhandler (target));
The target method of the target object is executed by executing the proxy method of the proxy object
proxy.login ();
Proxy.logout ();
}
3, the dynamic agent model is relatively difficult to understand, because it uses the reflection mechanism. But imagine real life, still quite easy to understand, for example, work intermediary, the equivalent of proxy model agent, it can for different people to find different jobs, we can not see our life everyone has a job intermediary agent object bar. So this can be understood as a function proxy object, that is, for all class agents to implement the same functionality, such as the top capture time.
Five, dynamic mode to resolve the service layer of the JDBC code, as well as some duplicate code:
Everyone until the service layer is used to write business code, but when things happen, we need to do things in the business layer to open, submit, rollback, end, so that there is the JDBC code, and are repeated, how to do it, We can solve this problem by using agent mode for the business layer that uses things.
Look at the method in the service layer, which has the JDBC code, and each servlet needs to be written, very unsatisfied with the spec:
public boolean saveenterprise (Enterprise en, list<eninv> Eninvs) throws Exception {Connection conn
;
int count=0;
try {
//Get Data Connection object
conn=dbutil.getconnection ();
The beginning of things
dbutil.begintransaction (conn);
Count=ienterpriserdao.insertenterprisedao (en, Eninvs);
The submission of things
dbutil.committransaction (conn);
} catch (Exception e) {
try {
//rollback
of Things Dbutil.rollbacktransaction (conn);
} catch (SQLException E1) {
e1.printstacktrace ();
}
E.printstacktrace ();
} finally{
try {
//end of thing
Dbutil.endtransaction (conn);
} catch (SQLException e) {
E.printstacktrace ();
}
DBUTIL.CLOSE (conn, NULL, NULL);
}
Return count== (1+eninvs.size ());
}
Dynamic Agent via ProX:
Authoring of Proxy methods:
public class Transactioninvcationhandler implements Invocationhandler {
//target object's creation
private object target;
Write the constructor method, public
Transactioninvcationhandler (Object target) {
this.target=target
}
@Override
/**
* Handling the invocation of things to handle
/Public
object Invoke (Object Proxy, approach method, object[] args) C12/>throws throwable {
Object retvalue=null;
Connection Conn=null;
try{
conn=dbutil.getconnection ();
Open things
dbutil.begintransaction (conn);
The method to execute the target object
retvalue=method.invoke (target, args);
Submit things
Dbutil.committransaction (conn);
} catch (Exception e) {
//rollback thing
dbutil.rollbacktransaction (conn);
E.printstacktrace ();
} finally{
//Close things
dbutil.endtransaction (conn);
DBUTIL.CLOSE (conn, NULL, NULL);
}
Return RetValue
}
}
This service will only need to write these two words:
public boolean saveenterprise (Enterprise en, list<eninv> Eninvs) throws Exception {
int count=0;
Count=ienterpriserdao.insertenterprisedao (en, Eninvs);
Return count== (1+eninvs.size ());
}
Of course the servlet call is the same as the test program above, and I don't write anymore. In a word, the dynamic proxy model imitates the intermediary agent in our life, so that our program code achieves very good reuse and classification clearly, very practical.
Other applications of Agent mode:
1, remote proxy, for an object in the different address space to provide local representation. This hides the fact that an object exists in a different address space.
2, the virtual agent, as needed to create expensive objects. It is used to store real objects that can take a long time to instantiate. For example, the page shows text before the picture comes out.
3, the security agent, used to control the real object access permissions.
4, intelligent agent, refers to when the real object is invoked, the agent to deal with other things.
In a word, this study, have feeling software and our life is closely related, good at discovering the life of dribs and drabs, from the software Lenovo Life will understand deeper, learn better ....