spring basic concepts AOP with dynamic proxy understanding

  • 2020-05-12 02:39:10
  • OfStack

1. Agency mode

The agency model is called Proxy or Surrogate in English, but it can also be translated into "agency" in Chinese. An agency means that one person or organization ACTS on behalf of another person or organization. In some cases, a client does not want to or cannot directly reference an object, and the proxy object ACTS as a mediator between the client and the target object.

Illustrate the agent differences by simply simulating the execution of a transaction

1.1 static proxy

Source code is created by a programmer or automatically generated by a particular tool and compiled. The proxy class's.class file already exists before the program runs.


public interface PersonDao {

 void savePerson();
}

public class PersonDaoImpl implements PersonDao {

 @Override
 public void savePerson() {
  System.out.println("save person");
 }
}


public class Transaction {
 
 void beginTransaction(){
  System.out.println("begin Transaction");
 }
 
 void commit(){
  System.out.println("commit");
 }
}

Next, write a static proxy class that implements the PersonDao interface


/**
 *  Static proxy class 
 * @author qjc
 */
public class PersonDaoProxy implements PersonDao{

 PersonDao personDao;
 Transaction transaction;
 
 public PersonDaoProxy(PersonDao personDao, Transaction transaction) {
  this.personDao = personDao;
  this.transaction = transaction;
 }

 @Override
 public void savePerson() {
  this.transaction.beginTransaction();
  this.personDao.savePerson();
  this.transaction.commit();
 }
}

test


/**
 *  Test static proxy 
 * @author qjc
 */
public class TestPersonProxy {
 
 @Test
 public void testSave(){
  PersonDao personDao = new PersonDaoImpl();
  Transaction transaction = new Transaction();
  PersonDaoProxy proxy = new PersonDaoProxy(personDao, transaction);
  
  proxy.savePerson();
 }
}

Conclusion:

1. The static proxy pattern does not achieve transaction reuse

2. Suppose dao has 100 classes and 100 proxy, how many methods are in the interface, how many methods must be implemented in proxy layer, and how many methods must open and commit transactions

3. If an proxy implements multiple interfaces, and if one of the interfaces changes (a method is added), then proxy should also change accordingly

1.2 JDK dynamic proxy

Dynamic proxy class: dynamically created using reflection while the program is running.

The dynamic proxy of JDK must meet four requirements: 1, target interface 2, target class 3, interceptor 4, and proxy class

Use the PersonDao interface, the PersonDaoImpl class, and the Transaction class from the previous example

Write interceptor


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 *  The interceptor  
 *   1 , the target class is imported in  
 *   2 , things come in  
 *   3 , invoke Completion: start the transaction, invoke the method of the target object, commit the transaction 
 * 
 * @author qjc
 */
public class Interceptor implements InvocationHandler {

 private Object target; //  The target class 
 private Transaction transaction;

 public Interceptor(Object target, Transaction transaction) {
  this.target = target;
  this.transaction = transaction;
 }

 /**
  * @param proxy  The proxy class instance of the target object 
  * @param method  Corresponding to calling the interface method on the proxy instance Method The instance 
  * @param args  An array of objects passed to the method parameter values on the proxy instance 
  * @return  Method. No return value is null
  * @throws Throwable
  */
 public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable {
  String methodName = method.getName();
  if ("savePerson".equals(methodName)
    || "deletePerson".equals(methodName)
    || "updatePerson".equals(methodName)) {

   this.transaction.beginTransaction(); //  Open the transaction 
   method.invoke(target); //  Calling the target method 
   this.transaction.commit(); //  Commit the transaction 

  } else {
   method.invoke(target);
  }
  return null;
 }
}

test


/**
 *  test jdk A dynamic proxy 
 * @author qjc
 */
public class TestJDKProxy {
 
 @Test
 public void testSave(){
  /**
   * 1 , create, 1 Target object 
   * 2 , create, 1 A transaction 
   * 3 , create, 1 An interceptor 
   * 4 , dynamic generation 1 Three proxy objects 
   */
  Object target = new PersonDaoImpl();
  Transaction transaction = new Transaction();
  Interceptor interceptor = new Interceptor(target, transaction);
  /**
   *  parameter 1 : sets the class loader used by the code, 1 Use the same classloader as the target class 
   *  parameter 2 : sets the interface implemented by the proxy class to use the same interface as the target class 
   *  parameter 3 : sets the callback object, which will be called when the method of the proxy object is called invoke methods 
   */
  PersonDao personDao = (PersonDao) Proxy.newProxyInstance(
    target.getClass().getClassLoader(),
    target.getClass().getInterfaces(),
    interceptor);
  personDao.savePerson();
 }
}

Conclusion:

1. Because the proxy class generated by JDKProxy implements the interface, all the methods in the target class are in the proxy class.

2. All methods of the generated proxy class intercept all methods of the target class. The content of the invoke method in the interceptor is the body of the various methods of the proxy class.

3, the use of JDKProxy must have the existence of interface.

4. The three parameters in the invoke method can access the API of the called method of the target class, the parameters of the called method, and the return type of the called method.

Disadvantages:

1. In addition to calling the target method of the target object, the functions in the interceptor are relatively simple. In this example, only transactions can be processed

2. The if judgment statement of the invoke method in the interceptor is unreliable in the real development environment, because many if statements need to be written.

1.3 CGLIB dynamic proxy

Use the PersonDaoImpl class and Transaction class from the previous example (without interfaces)

Write the interceptor class


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

/**
 * CGLIB The agent   The interceptor  
 * @author qjc
 */
public class Interceptor implements MethodInterceptor {

 private Object target; //  The target class of the proxy 
 private Transaction transaction;

 public Interceptor(Object target, Transaction transaction) {
  this.target = target;
  this.transaction = transaction;
 }

 /**
  *  Create a proxy object for the target object 
  * 
  * @return
  */
 public Object createProxy() {
  //  Code enhancement 
  Enhancer enhancer = new Enhancer(); //  This class is used to generate proxy objects 
  enhancer.setCallback(this); //  Parameter is interceptor 
  enhancer.setSuperclass(target.getClass());//  Set the parent class 
  return enhancer.create(); //  Create a proxy object 
 }

 /**
  * @param obj  An instance of the target object proxy class 
  * @param method  On the proxy instance   That calls a superclass method Method The instance 
  * @param args  An array of objects passed to the method parameter values on the proxy instance 
  * @param methodProxy  Use it to call the methods of the parent class 
  * @return
  * @throws Throwable
  */
 public Object intercept(Object obj, Method method, Object[] args,
   MethodProxy methodProxy) throws Throwable {
  this.transaction.beginTransaction();
  method.invoke(target);
  this.transaction.commit();
  return null;
 }
}

test


/**
 *  test cglib A dynamic proxy 
 *  through cglib The proxy class is a subclass of the target class 
 * @author qjc
 */
public class TestCglibProxy {
 
 @Test
 public void testSave(){
 
  Object target = new PersonDaoImpl();
  Transaction transaction = new Transaction();
  Interceptor interceptor = new Interceptor(target, transaction);
  
  PersonDaoImpl personDaoImpl = (PersonDaoImpl) interceptor.createProxy();
  personDaoImpl.savePerson();
 }
}

Conclusion:

1. CGlib is a powerful, high-performance, high-quality Code generated class library. It extends the Java class at runtime and implements the Java interface.

2. The proxy class generated with CGlib is a subclass of the target class.

3. No interface is required to generate proxy classes with CGlib

4. The proxy class generated by CGLib overrides the methods of the parent class.

5. The content of the intercept method in the interceptor is exactly the difference between the method body CGLIB and JDK dynamic proxy in the proxy class:

JDK:

The target and proxy classes implement a common interface

The interceptor must implement the InvocationHandler interface, where the content of the invoke method body is the content of the proxy object method body

CGLIB:

The target class is the parent of the proxy class

The interceptor must implement the MethodInterceptor interface, and the intercept method in the interface is the method body of the proxy class that creates the proxy object using the bytecode enhancement mechanism.

2. Aspect oriented programming

OOP(object-oriented programming) : encapsulation, inheritance, polymorphism, abstraction

Encapsulation, the basic management of the code, modular management. Each class may have its own function, the problem is to find people on the job. From a modification perspective, it can be risky to modify the code directly, which is not a long-term plan. The most natural change is from type encapsulation. However, how to integrate the new type with the old system? Therefore, it is necessary to establish a blood relationship between classes. So that's the requirement for inheritance, which is to find that these classes are related to each other, that they have a parent-child relationship with each other. Then polymorphism plays a decisive role on the basis of inheritance. Therefore, it is generally believed that the core feature of object orientation is polymorphism. The first couple of them are kind of laying the groundwork. Polymorphism is its core characteristic. Subclasses, by means of an override method, represent extending this level of things that work in the old system, and this is reusing this level of things, new methods, old systems, extensions, and reuse.

AOP(aspect oriented programming):

Section-oriented programming, is a precompiled run-time dynamic proxy to achieve the program dynamic system 1 without modifying the source code is a technology.

OOP and AOP:

OOP: abstract encapsulation of the entities and their attributes and behaviors of the business process for clearer lus partitioning.

AOP: extract the crosscutting logic from the business process, which is faced with a certain step or stage in the process to achieve the isolation effect of low coupling between the parts of the logical process. These two design ideas have essential differences in their goals. AOP enables reuse of code blocks.

spring AOP agent mechanism:

1, if the target object implements a number of interfaces, use spring JDK java. lang. reflect. Proxy class agent.

Advantages: the system is more loosely coupled because of the interface

Cons: create interfaces for each target class

2. If the target object does not implement any interface, spring USES the CGLIB library to subclass the target object.

Advantage: because the proxy class is inherited from the target class, no interface is required.

Cons: because no interface is used, the coupling of the system is not as good as with JDK's dynamic proxy.

Use the PersonDao interface, PersonDaoImpl class, and Transaction class from the first example

Write the spring configuration


 <bean id="personDao" class="cn.qjc.aop.xml.PersonDaoImpl"></bean>
 <bean id="transaction" class="cn.qjc.aop.xml.Transaction"></bean>
 
 <aop:config>
  <!--  Pointcut expression   Determine the target class  -->
  <aop:pointcut expression="execution(* cn.qjc.aop.xml.PersonDaoImpl.*(..))" id="perform"/>
 
  <!-- ref Pointing to an object is the tangent plane  -->
  <aop:aspect ref="transaction">
   <aop:before method="beginTransaction" pointcut-ref="perform"/>
   <aop:after-returning method="commit" pointcut-ref="perform"/>
  </aop:aspect>
 </aop:config>
 
</beans>

test


public class PersonDaoImpl implements PersonDao {

 @Override
 public void savePerson() {
  System.out.println("save person");
 }
}

0

spring AOP principle

1. When the spring container is started, load two bean and instantiate the bean container
2, when the spring container is resolved to the configuration file < aop:config > , parse out the pointcut expression and match the bean of the spring container contents according to the pointcut expression
3. If the match is successful, create a proxy object for the bean
4. When the client USES context.getBean to get an object, if the object has a proxy object, it will return the proxy object; if there is no proxy object, it will return the object itself


Related articles: