Static and dynamic agent Proxy agent model of the Java

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/TreeShu321/article/details/102640372


Agent Model Description:
proxy (Proxy) is a design pattern that provides an additional way to access the target object; that is accessed by the target through a proxy object benefits of doing so are: On the basis of the target object can be achieved on additional enhancements. functional operation of the expansion of the target object's function.
use this programming to a thought: Do not feel free to go at someone or modify the code already written, if the need to change the modification, the method can be extended by way of proxy

For example: we can buy a house through a real estate agent to purchase, without the need to go directly to property developers to buy, which is our intermediary proxy object.

Proxy mode by category can be divided into three categories:

  • Static agents
  • Dynamic proxy
    dynamic proxy can be divided into: jdk api dynamic proxy and proxy dynamic cglib

Static agents

When using static agent, need to define interfaces or parent class is the interface to achieve the same or the same parent is inherited along with the proxy object proxy object.

Code Example:
Proxy interface UserDao

package com.sl.proxy;

/**
 * @author shuliangzhao
 * @Title: UserDao
 * @ProjectName spring-boot-learn
 * @Description: TODO
 * @date 2019/10/19 17:02
 */
public interface UserDao {

    void delete();
}

Audience UserDaoImpl

package com.sl.proxy;

/**
 * @author shuliangzhao
 * @Title: UserDaoImpl
 * @ProjectName spring-boot-learn
 * @Description: TODO
 * @date 2019/10/19 17:02
 */
public class UserDaoImpl implements UserDao {
    @Override
    public void delete() {
        System.out.println("删除数据");
    }
}

Proxy object UserDaoProxy

package com.sl.proxy;

/**
 * 代理对象
 * @author shuliangzhao
 * @Title: UserDaoProxy
 * @ProjectName spring-boot-learn
 * @Description: TODO
 * @date 2019/10/19 17:03
 */
public class UserDaoProxy implements UserDao {

    private UserDao target;

    public UserDaoProxy(UserDao target) {
        this.target = target;
    }

    @Override
    public void delete() {
        System.out.println("开始操作");
        target.delete();
        System.out.println("结束操作");
    }
}

Test class App

public class App {

    public static void main(String[] args) {
        UserDaoImpl userDao = new UserDaoImpl();
        UserDaoProxy userDaoProxy = new UserDaoProxy(userDao);
        userDaoProxy.delete();
    }
}

Summary: call the proxy object method to invoke the target needs to be noted that the proxy object to the target object. Implement the same interface , and then call the target object by calling the same method of approach.
1. can be done in the function without modifying the target object, the target extensions.
2. Disadvantages: Because the proxy object needs to implement the same interface as the target object, and so many proxy class, class too much at the same time, once. Interface method for increasing the target object and proxy object must be maintained.

Dynamic Proxy

Dynamic characteristics of the agent:
1, proxy object, no need to implement the interface
2 to generate a proxy object, the JDK using the API, the dynamic proxy object constructed in memory

jdk generated proxy object

JDK implementation agent only need to use Proxy.newProxyInstance method, but this method requires three parameters, complete wording is:

static Object newProxyInstance(ClassLoader loader, Class<?>[]
interfaces,InvocationHandler h )

  • ClassLoader loader ,: audience used to specify the current class loader, the loader is to obtain a fixed
  • Class <?> [] Interfaces ,: type of target object implements an interface, use the generic way to confirm the type of
  • InvocationHandler h: event processing, when the method of execution of the target object, the event handler method will be triggered, the current method will execute the target object as a parameter

The sample code
creates UserDaoInvocationHandler class that implements the interface InvocationHandler, this class holds a proxy object is an instance of target

package com.sl.jdkproxy;

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

/**
 * @author shuliangzhao
 * @Title: UserDaoInvocationHandler
 * @ProjectName spring-boot-learn
 * @Description: TODO
 * @date 2019/10/19 17:14
 */
public class UserDaoInvocationHandler implements InvocationHandler {

    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理执行" +method.getName() + "方法");
        Object invoke = method.invoke(target, args);
        return invoke;
    }
}

Factory to create a proxy class

package com.sl.jdkproxy;

import java.lang.reflect.Proxy;

/**
 * @author shuliangzhao
 * @Title: ProxyFactory
 * @ProjectName spring-boot-learn
 * @Description: TODO
 * @date 2019/10/19 17:19
 */
public class ProxyFactory {

    //维护一个目标对象
    private Object target;
    public ProxyFactory(Object target){
        this.target=target;
    }

    //给目标对象生成代理对象
    public Object getProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new UserDaoInvocationHandler(target));
    }
}

Test class App

package com.sl.jdkproxy;

import com.sl.staticproxy.UserDao;
import com.sl.staticproxy.UserDaoImpl;

/**
 * @author shuliangzhao
 * @Title: App
 * @ProjectName spring-boot-learn
 * @Description: TODO
 * @date 2019/10/19 17:22
 */
public class App {

    public static void main(String[] args) {
        UserDao userDao = new UserDaoImpl();

        UserDao proxyInstance = (UserDao) new ProxyFactory(userDao).getProxyInstance();

        System.out.println(proxyInstance.getClass());

        // 执行方法   【代理对象】
        proxyInstance.delete();
    }
}

Summary: proxy object does not need to implement the interface, but the target object must implement the interface, or can not use dynamic proxies

Acting cglib

The above static and dynamic agent Proxy models are required to achieve the target object is a target object interface, but sometimes the target object is just a single object, and does not implement any interfaces, this time we can use the target object is a subclass agent class implements embodiment, this method is called: Cglib agent
Cglib is a powerful, high-performance code generator package, it can extend the java class are widely used and implemented in many AOP frame java interfaces at runtime, e.g. Spring. AOP and synaop, provides a method for their interception (interception)
using cglib proxy Note:
1. the agent class can not be final, otherwise an error
2. If the target object's method is final / static, then it will not be blocked, that is, the business method does not execute the target object additional
sample code:
the object being proxied UserDao

 */
public class UserDao {

    public void delete() {
        System.out.println("删除方法");
    }
}

Factory to create a proxy class

public class ProxyFactory implements MethodInterceptor {

    //维护目标对象
    private Object target;

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

    //给目标对象创建一个代理对象
    public Object getProxyInstance() {
        //1.工具类
        Enhancer enhancer = new Enhancer();
        //2.设置父类
        enhancer.setSuperclass(target.getClass());
        //3.设置回调函数
        enhancer.setCallback(this);
        //4.创建子类
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("开始事务...");

        //执行目标对象的方法
        Object returnValue = method.invoke(target, objects);

        System.out.println("提交事务...");

        return returnValue;
    }
}

Test category

public class App {

    public static void main(String[] args) {
        UserDao userDao = new UserDao();
        UserDao proxyInstance = (UserDao) new ProxyFactory(userDao).getProxyInstance();
        proxyInstance.delete();
    }
}

Guess you like

Origin blog.csdn.net/TreeShu321/article/details/102640372