The spring AOP proxy mode

 Let me talk java Object-Oriented (oop), object-oriented in some public act, like logging, etc. If you have permission to verify the use of object-oriented to do, will have to write duplicate code in each business process, vertical extraction mechanism to resolve, resulting in redundant code. Refers to the AOP Oriented Programming, extended functions implemented without modifying the source code, using horizontal extraction mechanism. A section defined by section to cut a corresponding method, can be woven into the associated logic. The AOP with the underlying dynamic proxy mode.

First, proxy mode

Proxy model as one of the 23 classic design patterns, comparing official definition is "to provide a proxy for other objects to control access to this object", the simple point that is, before the A class myself one thing, the use of after the agent, a class do not directly, but to be done by the proxy class B a class. In fact, the proxy class before the class is based on doing a layer package. java in static agents, JDK dynamic proxy, CGLib dynamic proxy. Static agent refers to the agent class is at compile existed , the opposite dynamic proxy is generated dynamically at runtime program .

Second, the static agent

Static agent, simply point, before the program is run, the relationship between the agent and the agent class category have been identified. Static agent implementations generally have the following steps, first define a common interface, and a proxy class for the proxy class implemented as follows:

Package com.bsoft.proxy2;
 / ** 
 * public interface 
 * / 
public  interface IUserDao { 

    void Save (); 

    void Find (); 
}

The proxy class (proxy target class):

Package com.bsoft.proxy2.impl; 

Import com.bsoft.proxy2.IUserDao;
 / ** 
 * are called proxy proxy class or certain classes 
 * / 
public  class UserDaoImpl the implements IUserDao { 
    @Override 
    public  void Save () { 
        the System.out. the println ( "simulated users save" ); 
    } 

    @Override 
    public  void Find () { 
        System.out.println ( "user query analog" ); 
    } 
}

Followed by proxy class

Package com.bsoft.proxy2.impl; 

Import com.bsoft.proxy2.IUserDao; 

/ ** 
 * proxy class 
 * / 
public  class UserDaoProxy the implements IUserDao { 

    Private UserDaoImpl UD = new new UserDaoImpl (); 

    @Override 
    public  void Save () { 
        the System .out.println ( "agent operation, open transaction" ); 
        ud.save (); 
        System.out.println ( "agent, close the transaction" ); 
    } 

    @Override 
    public  void Find () { 
        System.out.println ( "agency operations, open transaction"  );
        ud.find ();
        System.out.println ( "Oh agent operation, close the transaction" ); 
    } 
}

It will be seen that the logic of the proxy class holds a proxy class is instantiated in a proxy class, the method is called by the proxy agent object class instance, before the method additionally before or after the addition of other processing logic methods.

Finally, look at using the test method of the proxy class:

Package com.bsoft.proxy2; 

Import com.bsoft.proxy2.impl.UserDao;
 Import com.bsoft.proxy2.impl.UserDaoProxy;
 Import org.junit.Test; 

public  class Test2 { 

    / ** 
     * not using a proxy, directly the proxy class 
     * / 
    public   void test1 () { 
        System.out.println ( "unused proxy mode ------ ----------" ); 
        iUserDao iUserDao = new new UserDao (); 
        iUserDao .save (); 
        System.out.println ( "----------------" ); 
        iUserDao.find (); 
    } 

    / ** 
     * static agent
     * Static agents and without the use of a static agents can be found after use of the agent can be added to other code before execution of the agent or after the method to achieve such operation and permission logs 
     * / 
    @Test 
    public  void test2 () { 
        the System .out.println ( "static proxy mode ------- --------" ); 
        iUserDao iUserDao = new new UserDaoProxy (); 
        iUserDao.save (); 
        System.out.println ( "- ------------------ " ); 
        iUserDao.find (); 
    } 
}

Test1 test execution returned the following results:

------ ---------- not use a proxy mode
simulation to save the user
----------------
simulate user queries

Test2 test execution returned the following results:

Static mode -------- ------- proxy 
agent operation, open affairs 
analog save the user 
agent, close the transaction
 ------------------- - 
agency operations, open affairs 
analog to query the user 
agent operation Oh, shut Affairs

After comparison, the use of static agent and does not use static agent, a proxy can be found, can be added to other code before or after the execution of the proxy method to achieve such operation and permission logs.

However, there are some static agents, a lot if the proxy method, it is necessary for each proxy method, increasing the cost of code maintenance. There are no other ways to reduce maintenance of the code, and that is dynamic proxy.

Three, JDK dynamic proxies

JDK provides dynamic proxy mode, may generate the proxy class, the proxy is seen proxy class interfaces and classes inherit static agent and the IUserDao UserDaoImpl following:

Package com.bsoft.proxy3; 

Import java.lang.reflect.InvocationHandler;
 Import the java.lang.reflect.Method; 

/ ** 
 * JDK dynamic proxy class 
 * / 
public  class DynamicProxy the implements of InvocationHandler { 

    // the proxy instance 
    Private IUserDao iUserDao ; 

    // Constructors 
    public DynamicProxy (IUserDao iUserDao) {
         the this .iUserDao = iUserDao; 
    } 

    @Override 
    public Object Invoke (Object Proxy, method, method, Object [] args) throws the Throwable { 
        Object Result = null; 
        System.out.println ( "start jdk dynamic proxy" ); 
       the Result = Method.invoke (iUserDao, args); 
        System.out.println ( "End jdk dynamic proxy" ); 
        System.out.println ( "the Result == == "+ Result);
         return Result; 
    } 
}

InvocationHandler need to implement the interface in the JDK, invoke methods implemented therein, the proxy class methods are called by this method in reflection mode, other processing may be performed before or after the method, see the following test code:

Package com.bsoft.proxy3; 

Import com.bsoft.proxy2.impl.UserDaoImpl; 

Import the java.lang.reflect.Proxy; 

public  class the Test3 { 

    / ** 
     * JDK dynamic proxy test 
     * / 
    public  static  void main (String [] args ) { 

        UserDaoImpl userDao = new new UserDaoImpl (); 
        DynamicProxy DynamicProxy = new new DynamicProxy (userDao); 

        // generate a proxy object for the first class loader is the proxy class, the second interface is implemented as a proxy class, the third It was invocationHandler implementation class, thus generating a proxy object 
        iUserDao iUserDao = (IUserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(),dynamicProxy);
        iUserDao.save();
        System.out.println("------------------");
        iUserDao.find();
    }
}

In the test code newProxyInstance by the method of the Proxy class userDao generate an instance of the proxy class, requires three parameters, the first being a class loader for the proxy class, the second interface is implemented as a proxy class, the third to invocationHandler implementation class, thus generating a proxy object, the proxy is then performed by calling the object method was as follows:

Start jdk dynamic proxy 
simulation to save the user 
end jdk dynamic proxy 
the Result ==== null 
------------------ 
start jdk dynamic proxy 
simulate user queries 
end jdk dynamic proxy 
the Result === = null

As can be seen from the above Proxy proxy class is dynamically generated by the class newProxyInstance method, the object is generated using the "call instance method" means a method call, the proxy class relations is only a proxy class in the implementation of this line of code when will generate, thus becoming a dynamic proxy.

JDK dynamic proxy also shortcomings, i.e. proxy class must be implemented interfaces, such interfaces can not be used without JDK dynamic proxies (known from the second parameter newProxyInstance method, must pass the proxy class interfaces be implemented ), you need to use CGLib dynamic proxy.

Four, CGLib dynamic proxies

CGLib dynamic proxy is a third-party implementations of dynamic proxy class library, not required to be proxy class must implement the interface, it uses a proxy class to be inherited, use its subclasses, is up for the lack agent class does not interface,

To use CGLib must be the introduction of third-party libraries. asm-3.2.jar, cglib-2.22.jar.

To use CGLib proxy, the proxy class needs to implement its MethodInterceptor Interface:

package com.bsoft.proxy4;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * cglib动态代理
 */
public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("开始CGLib动态代理");
        Object object=proxy.invokeSuper(obj, args);
        System.out.println("结束CGLib动态代理");
        return object;
    }
}

The proxy class:

Package com.bsoft.proxy4; 

public  class TeacherDao { 

    public  void Save () { 
        System.out.println ( "teacher analog save" ); 
    } 

    public  void Find () { 
        System.out.println ( "Query teacher analog" ); 
    } 
}

Which test code is as follows:

Package com.bsoft.proxy4; 

Import the net.sf.cglib.proxy.Enhancer; 

public  class Test4 { 

    / ** 
     * CGLIB dynamic proxy test 
     * @param args
      * / 
    public  static  void main (String [] args) { 
        Enhancer Enhancer = new new Enhancer (); 
        enhancer.setSuperclass (. TeacherDao class ); 
        enhancer.setCallback ( new new MyMethodInterceptor ());
         // generate proxy classes 
        TeacherDao teacherDao = (TeacherDao) enhancer.create (); 
        teacherDao.save ();
        System.out.println("----------------");
        teacherDao.find();
    }
}

It can be seen Enhancer used to generate the proxy class, need to be set proxy class, which is the parent class (here can be seen to use inheritance, generated subclass), provided callback method.

Start CGLib dynamic proxy 
analog save teachers 
end CGLib dynamic proxy
 ---------------- 
start CGLib dynamic proxy 
simulation queries teacher 
ended CGLib dynamic proxies

In setting the time you need to pass a callback enhancer.setCallback MethodInterceptor instance, where an anonymous inner classes can be used.

V. Summary

 Static agents, JDK dynamic proxy, CGLib dynamic proxies to make a summary, the static agent maintenance costs are high, there is a need to create a proxy class agent class, and the need to implement the same interface. JDK dynamic proxy mode and CGLib dynamic proxies difference is the need to be implemented JDK dynamic proxy interface agent class, but CGLib is generated proxy class is a subclass of, asked to be the agent class can not be final because the final class can not be inherited.

Guess you like

Origin www.cnblogs.com/mabaoying/p/11286225.html