4
头图

Preface

Proxy mode is a structure type design mode, which provides another way to is to access the target object through the proxy object.

image-20210724125009890

The advantage of doing this is: on the basis of the realization of the target object, additional functional operations can be enhanced, that is, the function of the target object can be expanded.

A thought in programming is used here: Don't modify the code or method that others have written at will. If you need to modify it, you can extend the method by proxy.

proxy model has roughly three roles:

  • Real Subject : The real class, that is, the agent class and the delegated class. Used to truly complete business service functions;
  • Proxy : The proxy class implements its own request with the function corresponding to the Real Subject, and the proxy class object does not really implement its business functions;
  • Subject : Define the interfaces that RealSubject and Proxy roles should implement.

image-20210724125955100

There are three types of proxy modes, static proxy, dynamic proxy (JDK proxy, interface proxy), Cglib proxy (subclasses of the target object are dynamically created in memory)

text

Static proxy

The static proxy needs to define the interface first, the proxy object and the proxy object implement the same interface together, and then calls the method of the target object by calling the same method.

image-20210726222112024

can see that the proxy class is nothing more than adding some operations before and after calling the delegate class method. The difference in the principal class also leads to the difference in the proxy class.

A certain company produces TV sets and needs to find an agent for sales in the local area. When a customer needs to buy a TV, he can buy it directly through an agent.

code example:

TV set:

public class TV {

    private String name;//名称

    private String address;//生产地

    public TV(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "TV{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

Create company interface:

public interface TVCompany {

    /**
     * 生产电视机
     * @return 电视机
     */
    public TV produceTV();
}

The company’s factory produces TV sets:

public class TVFactory implements TVCompany {
    @Override
    public TV produceTV() {
        System.out.println("TV factory produce TV...");
        return new TV("小米电视机","合肥");
    }
}

The agent places an order to get the goods (static agent type):

public class TVProxy implements TVCompany{

    private TVCompany tvCompany;

    public TVProxy(){

    }

    @Override
    public TV produceTV() {
        System.out.println("TV proxy get order .... ");
        System.out.println("TV proxy start produce .... ");
        if(Objects.isNull(tvCompany)){
            System.out.println("machine proxy find factory .... ");
            tvCompany = new TVFactory();
        }
        return tvCompany.produceTV();
    }
}

Consumers get the goods through agents (the use of agents):

public class TVConsumer {

    public static void main(String[] args) {
        TVProxy tvProxy = new TVProxy();
        TV tv = tvProxy.produceTV();
        System.out.println(tv);
    }
}

Output result:

TV proxy get order .... 
TV proxy start produce .... 
machine proxy find factory .... 
TV factory produce TV...
TV{name='小米电视机', address='合肥'}

Process finished with exit code 0

summary:

  • Advantages: The static proxy mode realizes the function expansion of the target object without changing the target object.
  • Disadvantages: The static proxy implements all methods of the target object. Once methods are added to the target interface, the proxy object and the target object must be modified accordingly, which increases maintenance costs.
How to solve the shortcomings in static proxy? The answer is that you can use dynamic proxy

Dynamic proxy

image-20210726224121229

Dynamic agents have the following characteristics:

  1. JDK dynamic proxy objects do not need to implement interfaces, only target objects need to implement interfaces.
  2. To realize the dynamic proxy based on the interface, you need to use the API in the JDK to dynamically construct the Proxy object in the JVM memory.
  3. Need to use java.lang.reflect.Proxy , and its newProxyInstance method, but this method needs to receive three parameters.

image-20210724132028289

Note that this method is a static method in the Proxy class, and the three parameters received are in order:

  • ClassLoader loader : Specify the current target object to use the class loader, and the method of obtaining the loader is fixed.
  • Class<?>[] interfaces : The type of the interface implemented by the target object, and the generic method is used to confirm the type.
  • InvocationHandler h : Event processing, when the method of the target object is executed, the method of the event handler will be triggered, and the method of the target object currently executed will be passed in as a parameter.
One day the company increased its business, sold more and more products, and needed more after-sales. But the company found that the original agent had to be retrained to complete all the business, so it found another dynamic agent B. Agent B promises to seamlessly connect all the company's business, no matter what new business is added, it can be completed without additional training.

code example:

The company has added maintenance services:

public interface TVCompany {

    /**
     * 生产电视机
     * @return 电视机
     */
    public TV produceTV();

    /**
     * 维修电视机
     * @param tv 电视机
     * @return 电视机
     */
    public TV repair(TV tv);
}

The factory also has to start the maintenance business:

public class TVFactory implements TVCompany {
    @Override
    public TV produceTV() {
        System.out.println("TV factory produce TV...");
        return new TV("小米电视机","合肥");
    }

    @Override
    public TV repair(TV tv) {
        System.out.println("tv is repair finished...");
        return new TV("小米电视机","合肥");
    }
}

B agent comprehensive agent for all the company's business. Use Proxy.newProxyInstance method of generating a proxy object to achieve InvocationHandler in invoke method, invoke by calling method reflected in the proxy class methods, and to provide an enhanced method.

public class TVProxyFactory {

    private Object target;

    public TVProxyFactory(Object o){
        this.target = o;
    }

    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),
                new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("TV proxy find factory for tv.... ");
                Object invoke = method.invoke(target, args);
                return invoke;
            }
        });
    }
}

purchase and repair these two services B agent can be done directly. If the company increases its business later, Agent B can do the same.

public class TVConsumer {

    public static void main(String[] args) {
        TVCompany target = new TVFactory();
        TVCompany tvCompany = (TVCompany) new TVProxyFactory(target).getProxy();
        TV tv = tvCompany.produceTV();
        tvCompany.repair(tv);
    }
}

Output result:

TV proxy find factory for tv.... 
TV factory produce TV...
TV proxy find factory for tv.... 
tv is repair finished...

Process finished with exit code 0

summary:

  1. proxy object does not need to implement the interface, but the target object must implement the interface, otherwise dynamic proxy cannot be used.
  2. dynamic proxy mode, all function calls will eventually be forwarded by the invoke function, so we can do some operations we want here, such as logging system, transaction, interceptor, permission control, etc.

One of the most fatal problems of JDK dynamic proxy is that it can only proxy the implementation class that implements an interface, and the proxy class can only proxy the methods implemented in the interface. If the implementation class has its own private method, but the interface does not If so, this method cannot be used for proxy calls.

solve this problem? We can use CGLIB dynamic proxy mechanism.

Cglib proxy

Both static proxy and JDK proxy require an object to implement an interface. Sometimes the proxy object is just a single object. In this case, Cglib proxy can be used.

image-20210726224750356

The Cglib agent can be called a subclass agent, which constructs a subclass object in memory to achieve the expansion of the target object function.

Agent C not only wants to act for the company, but also wants to act for products from multiple factories.

Cglib by Enhancer generates a proxy class, by implementing MethodInterceptor interface, and wherein the implemented intercept method, may be added in this process enhancement methods, and can use the reflective Method or MethodProxy inheritance class to call the original method.

Seeing that the B has undertaken a variety of business (interface) of the company, then at this time agent C has discovered new business opportunities from it. B can only represent the products of a certain company, and I not only want to represent the company’s products, Moreover, it connects with different factories, has wider channels for getting goods, and makes money more freely. So Cglib is used.

code example:

public class TVProxyCglib implements MethodInterceptor {

    //给目标对象创建一个代理对象
    public Object getProxyInstance(Class c){
        //1.工具类
        Enhancer enhancer = new Enhancer();
        //2.设置父类
        enhancer.setSuperclass(c);
        //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("TVProxyFactory enhancement.....");
        Object object = methodProxy.invokeSuper(o, objects);
        return object;
    }
}

New agent's B factory

public class TVFactoryB {

    public TV produceTVB() {
        System.out.println("tv factory B producing tv.... ");
        return new TV("华为电视机", "南京");
    }

    public TV repairB(TV tv) {
        System.out.println("tv B is repair finished.... ");
        return tv;
    }
}

C agent can directly cooperate with the company, or deal with the factory. And can act as an agent for any factory's products.

public class TVConsumer {

    public static void main(String[] args) {
        TVCompany tvCompany = (TVCompany) new TVProxyCglib().getProxyInstance(TVFactory.class);
        TV tv = tvCompany.produceTV();
        tvCompany.repair(tv);
        System.out.println("==============================");

        TVFactoryB tvFactoryB = (TVFactoryB) new TVProxyCglib().getProxyInstance(TVFactoryB.class);
        TV tv = tvFactoryB.produceTVB();
        tvFactoryB.repairB(tv);
    }
}

Output result:

TVProxyFactory enhancement.....
TV factory produce TV...
TVProxyFactory enhancement.....
tv is repair finished...
==============================
TVProxyFactory enhancement.....
tv factory B producing tv.... 
TVProxyFactory enhancement.....
tv B is repair finished.... 

Process finished with exit code 0

AOP uses proxy in Spring

There are two implementations of AOP in Spring, JDK and Cglib, as shown below:

image-20210724133134109

If the target object needs to implement an interface, use the JDK proxy.

If the target object does not need to implement the interface, use the Cglib proxy.

Summarize

  1. 1610212b30c73e Static proxy proxy class and the target class need to implement interface methods, so that the proxy can enhance its functions.
  2. the JDK dynamic proxy: the need for a proxy class implements an interface, use Proxy.newProxyInstance generated proxy class methods, and implement InvocationHandler in invoke way to achieve enhanced functionality.
  3. Cglib Dynamic Agent: Agent class implements interfaces without using Cblib the Enhancer generates child proxy object class and implement MethodInterceptor in intercept method, this method can achieve enhanced functionality.

at last

I am a code farmer who is being beaten and working hard to advance. If the article is helpful to you, remember to like and follow, thank you!


初念初恋
175 声望17 粉丝