Three Agent Ways of Spring

Keywords: Java JDK Spring jvm

I. Static Agent

The proxy object implements the same interface as the target object.
eg: 
    //Save user
    UserDao(save)Direct preservation
    UserDaoProxy Add transaction processing to the save method

IUserDao.java Target Object Implementation Interface
public interface IUserDao{
    void save();
}

UserDao.java  Target object
public class UserDao{
    public void save(){
      System.out.println("Saved data")
    }
}

ProxyFactory.java  Surrogate object
public class ProxyFactory implements IUserDao{
//Maintaining a target object
private IUserDao target;
public ProxyFactory(target){
this.target=target;
  }
}
public void save(){
    System.out.println("Transaction opening");
    target.save();
    System.out.println("Transaction closure");
}

TestMain.java
public class TestMain{
    @Test
    public void test(){
        IUserDao target =new UserDao();
        IUserDao proxy=new ProxyFactory(target);
        proxy.save();
    }
}

//Summarize static proxy:
1)It can extend the function of the target object without modifying the function of the target object.
2)Disadvantages:
    -->  Because the proxy object needs the same interface as the target object. So there will be many proxy classes, too many classes.
    -->  Once the interface adds methods, both the target object and the proxy object are maintained.

II. Dynamic Agent

1) Proxy object, no need to implement interface;
2) Proxy object generation is to construct proxy object dynamically in memory by using JDK API (we need to specify the type of interface to create proxy object/target object);
3) Dynamic proxy, JDK proxy, interface proxy;
API for generating proxy objects in JDK:
|– Proxy
static Object newProxyInstance(
ClassLoader loader, specifying that the current target object uses a class loader
Class<? > [] interfaces, the type of interface that the target object implements
Invocation Handler h Event Processor
)

IUserDao. Java UserDao. Java Ibid.

// Agent Factory does not need to implement IUserDao
public class ProxyFactory{

    // Maintaining a target object
    private Object target;

    public ProxyFactory(Object target){
        this.target=target;
    }

    // Generating proxy objects
    public Object getProxyInstance(){
        return Proxy.newProxyInstance(
        target.getClass().getClassLoader(),
        target.getClass().getInterfaces(),
        new InvacationHandler(){
        @Override
        public Object invoke(Object proxy,Method method,Ojbect[] args)
            throws Throwable{
            System.out.println("Open Transaction");
            // Executing the Target Object Method
            Object returnValue=method.invoke(target,args);
            System.out.println("commit transaction");
            return returnValue;
            }
        });
    }
}

App.java
public class App{
    IUserDao target =new UserDao();
    IUserDao proxy=new ProxyFactory(target).getProxyInstance();
    proxy.save();

}


Dynamic Agent Summary:
The proxy object does not need to implement the interface, but the target object must implement the interface; otherwise, the dynamic proxy can not be used!
(class  $Proxy0  implements IuserDao)



Reflection:
    There is a target object, want to expand the function, but the target object does not realize the interface, how to expand the function?
    Class  UserDao{}
    // Ways of subclassing
    Class subclass  extends  UserDao{}

    Implementing it as a subclass (cglib proxy)

III. cglib Agent
Cglib proxy, also known as subclass proxy. A subclass object is constructed in memory to extend the function of the target object.

JDK's dynamic proxy has a limitation that objects using dynamic proxy must implement one or more interfaces. If you want to proxy classes that do not implement interfaces, you can use CGLIB to implement them.
CGLIB is a powerful and high performance code generation package that can extend Java classes and implement Java interfaces at runtime. It is widely used by many AOP frameworks, such as Spring AOP and dynaop, to provide interception of methods for them.
The bottom layer of CGLIB package is to convert bytecode and generate new classes by using a small and fast bytecode processing framework ASM. Direct use of ASM is discouraged because it requires you to be familiar with the internal structure of JVM, including the format and instruction set of class files.

Cglib Subclass Agents:
    1) Need to introduce cglib – jar Documents, however spring The core package is already included cglib Functions, so direct introduction spring-core-3.2.5.jar Yes.
    2)With the introduction of functional packages, subclasses can be dynamically constructed in memory
    3)A proxy class cannot be final, Otherwise, the error will be reported.
    4) If the method of the target object is final/static, Then it will not be intercepted, that is, it will not execute additional business methods on the target object.


//In Spring's AOP programming,
    //If the object added to the container has an implementation interface, it is proxyed by JDK.
    //If the target object does not implement the interface, Cglib proxy is used.

    //No IUser Dao is available
    UserDao Ditto

    ProxyFactory.java
    public class ProxyFactory implements MethodInterceptor{
        private Object target;
        public ProxyFactory(Object target){
            this.target=target;
        }

        // Create proxy objects for target objects
        public Object getProxyInstance(){
            //1. tool class
            Enhancer en = new Enhancer();
            //2. Setting parent class
            en.setSuperclass(target.getClass());
            //3. Setting callback function
            en.setCallback(this);
            //4. Create subclasses (proxy objects)
            return en.create();
        }

        @Override
        public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable{

            System.out.println("Open transaction");
            Object returnValue=method.invoke(target,args);
            System.out.println("Closing transaction");
            return returnValue;
        }
    }

    App.java
    public class App{
        @Test
        public void test(){
            UserDao target=new UserDao();
            UserDao proxy=(UserDao)new ProxyFactory(target).getProxyInstance();
            proxy.save();
        }
    }

Posted by latvaustin on Fri, 19 Apr 2019 23:48:33 -0700