java design patterns ---- proxy mode, the jdk dynamic proxy and understand cglib dynamic proxies difference

Proxy mode:

It refers to provide an agent for other objects, to control access to the object.

Proxy object mediates between the customer and target objects.

It is structural design patterns.

Proxy pattern classification:

Static agent.

Dynamic proxies.

 

Static agents

Okay, so we start with the static proxy:

Role analysis:

1. abstract role: general use interfaces or abstract classes to solve

2. The true role: the role of agent

3. Acting Role: real role, the real role of the agent, we will do some general operating subsidiary

4. Customer: people accessing the proxy object

Code Step:

1. Interface

/**
 * @Author Darker
 * @Descrption 租房
 * @Date : Created in 10:00 2020-3-11
 */
public interface Rent {
    public void rent();
}

2, the real role

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 10:01 2020-3-11
 */
public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东出租房子");
    }
}

3, Acting Role

/**
 * @Author Darker
 * @Descrption 代理,中介
 * @Date : Created in 10:02 2020-3-11
 */
public class Proxy{

    private Host host;

    public Proxy(){}

    public Proxy(Host host){
        this.host = host;
    }

    public void rent(){
        seeHouse();
        host.rent();
        signContract();
        fare();
    }

    public void seeHouse(){
        System.out.println("中介带你看房子");
    }

    public void signContract(){
        System.out.println("签租房合同");
    }

    public void fare(){
        System.out.println("收中介费");
    }
}

4, Client Access

/**
 * @Author Darker
 * @Descrption 客户端租房
 * @Date : Created in 10:02 2020-3-11
 */
public class Client {
    public static void main(String[] args) {
        Host host = new Host();
        Proxy proxy = new Proxy(host);
        proxy.rent();
    }
}

Static proxy mode benefits:

1. You can make the operation more real characters keep pure! Do not have to pay attention to some of the public's business.

2. The public role to the agent role! To achieve the division of the business!

3. Public service occurs when extended, easy centralized management.

Disadvantages:

A role it will have a real acting role, will double the amount of code.

 

Of course, the above example may not be common in our actual development, but mainly to understand the significance agency model, we now give the application a code, Take curd Laijiangjiang.

1, first of all we have a company business is the operation of the user's curd;

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 10:19 2020-3-11
 */
public interface UserService {
    public void add();

    public void delete();
}

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 10:20 2020-3-11
 */
public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("增加一个角色");
    }

    @Override
    public void delete() {
        System.out.println("删除一个角色");
    }
}

2, well, now the question is, our company requires every step to add logs.

First think, to each method plus userImpl inside the log operation, it is too silly, but also not wearing them, and not in line with the opening and closing principle.

So, we thought of agency model, we use a proxy to complete.

/**
 * @Author Darker
 * @Descrption 静态代理模式
 * @Date : Created in 10:26 2020-3-11
 */
public class Proxy implements UserService{
    
    private UserServiceImpl userService;

    public void setUserService(UserServiceImpl userService) {
        this.userService = userService;
    }

    @Override
    public void add() {
        log("add");
        userService.add();
    }

    @Override
    public void delete() {
        log("delete");
        userService.delete();
    }

    public void log(String msg){
        System.out.println("调用了"+msg+"方法");
    }
    
}

/**
 * @Author Darker
 * @Descrption 客户端
 * @Date : Created in 10:20 2020-3-11
 */
public class Client {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        Proxy proxy = new Proxy();
        proxy.setUserService(userService);
        proxy.add();
    }
}

In this way, we've had to add a log feature, but in line with the principle of opening and closing, while reducing the coupling, which is the application of a static proxy mode.

However, this should be a proxy for each real role, as each of the above service to be a proxy, or too much trouble, how to solve it, as a programmer will certainly think of using reflection, just a simple factory, I do not want to pass the string into which sub-class distinction, and I'm going straight pass class, and then use reflection to automatically generate the kind of factory, then we are not also be directly reflected automatically generated proxy class we want to proxy it, thinking there , and specifically how to achieve?

Dynamic Proxy

1, the role of analysis: static and dynamic proxy agent role as

2, the dynamic proxy class is automatically generated dynamically, not our direct written

3, dynamic proxy divided into two categories: dynamic agent-based interface, dynamic proxy class-based

    * ---- jdk dynamic proxy-based interface

    * Class-based: cglib

    * Java bytecode: javasist (Learn to become slightly lower)

 

jdk dynamic proxy

Here we focus on in terms of dynamic proxies under jdk, first of all we must first understand two classes: Proxy (proxy), invocationHandler (call processing)

Api InvocationHandler take a look at this class, we can see that it is a reflection interface in the package, then we know that it does use a reflective technology.

We point go in and see it only one way to find

 Well, then let's look at the next class proxy

 

Similarly, it is also a reflection of the package the following classes, but it tells you two ways to create a proxy 

The method is to call a method that getProxyClass first obtain a Constructor object, then the object newInstance use this constructor to construct the object, and you pass the handler passed in the last return a proxy class you want.

Method 2 is more simple and straightforward method to return the call newProxcyInstance direct proxy class for the object. 

Firstly, our aim is to obtain a dynamic proxy, that means I preach what I like to come in return should give a proxy object, the object we need to have a way to do a little operation you want to operate on the proxy class, it can be seen from api's just, this is equivalent to invocationHadler abstract interface we need to implement, as renters behavior we first static agent in (a proxy class and real class common method).

1. Universal proxy generation who can represent any interface, return the proxy class object you want.

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 11:42 2020-3-11
 */
public class DynamicProxyProvider implements InvocationHandler {
    //被代理的接口
    private Object target;

    public void setObject(Object target) {
        this.target = target;
    }

    //第一个参数是为了加载类在哪个位置classLoader
    //代理类的接口
    //自己本身
    public Object getProxy(){
      return  Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }


    //从参数可以看出我们需要一个代理类,所以我们来一个方法生成代理类
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        Object invoke = method.invoke(target, args);
        return invoke;
    }

    public void log(String msg){
        System.out.println("调用了"+msg+"方法");
    }
}

2. The need for interfaces and entities agent.

/**
 * @Author Darker
 * @Descrption 租房
 * @Date : Created in 10:00 2020-3-11
 */
public interface Rent {
    public void rent();
}


/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 10:01 2020-3-11
 */
public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东出租房子");
    }
}

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 10:19 2020-3-11
 */
public interface UserService {
    public void add();

    public void delete();
}

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 10:20 2020-3-11
 */
public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("增加一个角色");
    }

    @Override
    public void delete() {
        System.out.println("删除一个角色");
    }
}

3. The client calls according to agent demand

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 11:50 2020-3-11
 */
public class Client {
    public static void main(String[] args) {
        Rent rent = new Host();
        DynamicProxyProvider proxyProvider = new DynamicProxyProvider();
        proxyProvider.setObject(rent);
        Rent proxyRent =(Rent) proxyProvider.getProxy();
        proxyRent.rent();

        UserServiceImpl userService = new UserServiceImpl();
        proxyProvider.setObject(userService);
        UserService proxyUserService = (UserService) proxyProvider.getProxy();
        proxyUserService.add();
    }
}

 

 It is not magic, use a proxy, you may want to interface enhancements, such as adding a log, add operational records.

advantage:

1. has all the advantages of a static agents

2. A dynamic proxy proxy class is an interface, generally corresponding to a class of service that

3. A dynamic proxy class can represent a plurality of classes, as long as the interface to achieve the same

but! but! but! ! ! ! After these two classes it in the end is how to do it dynamically generated proxy, why do I add a method in which invoke method, each agent class method I will change it?

Well, we now analyze dynamic proxy implementation principle.

1. the proxy class to get a reference, and obtains all of its interfaces (acquired reflection). Note: Why not direct proxy class, have to form an interface to the agent, because it is all the code reflection method of obtaining interfce.

2.jdk Proxy class to regenerate a new class that implements all methods of the interface is the proxy class.

3. dynamically generated java code, the enhance logic is added to the newly generated code.

4. The new java code compiled class files.

5. Load and re-run the new class, the class is to get a new class.

Why we get a whole new class of it, we have to look at the output of the class look, we will find its type into a $ Proxy1 instead UserServiceImpl.

 

Jdk in the end it is not as we would like it to do so, we enter its approach to see.

 

Sure enough, it was rebuilt a class, which may explain why it can enhance our approach, and it put all methods to rewrite it again, to see if it is anti-compiled class files, you will also find it the methods are final, meaning that it can only be a proxy (also, realize why the above is less than the length of the interface 65535 it, I found the answer in a blog from others).

 cglib dynamic proxy

The above talked of jdk dynamic proxy, discovered a problem that can only have agents all subclasses of a general interface to rewrite a new class through all the ways you can scan inside this interface, then the question is, if we no interface how to do, I have only one class, of course, there are solutions that cglib dynamic proxy to achieve.

1. cglib first to write a proxy class (cglib implementation is a packet interceptor under it MethodInterceptor, by proxy by proxy class that you want to set it in the form of the parent class, that is, the use of the principle of inheritance, the subclass can inherit the parent class and the parent class rewrite)

/**
 * @Author Darker
 * @Descrption 实现一个cglib的拦截器
 * @Date : Created in 16:32 2020-3-11
 */
public class CGlibProxyPriveder implements MethodInterceptor {

    public Object getProxy(Class<?> clazz){
        //相当于cglib给你写了个生成代理的工具类,你只要把class传进来就可以了
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) {
        log(method.getName());
        try {
            methodProxy.invokeSuper(o,objects);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

    public void log(String msg){
        System.out.println("调用了"+msg+"方法");
    }
}

2. the proxy class does not implement interface, of course, also be implemented, and primarily to distinguish the jdk dynamic proxy.

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 17:34 2020-3-11
 */
public class UserImpl {
    public void add(){
        System.out.println("添加一个用户");
    }
}

3. Run

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 17:36 2020-3-11
 */
public class CGlibTest {
    public static void main(String[] args) {
        CGlibProxyPriveder cGlibProxyPriveder = new CGlibProxyPriveder();
        UserImpl cGlibProxy = (UserImpl)cGlibProxyPriveder.getProxy(UserImpl.class);
        cGlibProxy.add();
    }
}

ok, successful, it seems cglib also completed our proxy function.

 

to sum up:

1.jdk dynamic proxy mechanism is implemented using the reflection, which is oriented interface; cglib the dynamic agent based bytecode underlying proxy class inheritance to achieve, CGLib is a powerful, high-performance Code library production, can be achieved run-time dynamic expansion java class (because it is inherited achieve, so if the proxy class if modified by the final keyword, it will fail).

2. With regard to both performance issues:

CGLib dynamic proxy object created in the performance of the actual running time of high JDK dynamic proxy lot, because it generates a logic all of FastClass included, which contains the method is called, do not need to be invoked through reflection than there studies have shown that speed is about 10 times higher;

But when the time CGLib create objects than it takes a lot more JDK dynamic proxy, proxy generation logic because cglib more complex, studies have shown that about 8 times the gap;

Thus, for a proxy object or a proxy instance of singleton pool, because without frequent create a proxy object, it is more suitable for CGLib dynamic proxy, anyway, is more suitable for JDK dynamic proxy.

 

Proxy Mode and spring

Well, we always say springAop achieve is to use the agency model, then you know what it is with the agent to achieve a dynamic thing, and now we have to find the spring-aop following ProxyFactoryBean take a look inside to find getObject method.

You'll see it here, there is a judgment, if you want the proxy class is a singleton, it returns a singleton type of proxy, if multi-cases, returns proxy more than one case, we look at the return singleton of.

 

From the above judgment may know, but there are bean implements the interface, while the configuration file is not configured to use force when cglib proxy, it will automatically use jdk dynamic proxy, or if this is not bean interface, then it will be used to dynamically cglib proxy.

Attachment:

Configuration cglib open configuration (it can be seen, in fact, are derived from the source to configure, and here are four ways to scan mybatis class have the same purpose):

 

Published 27 original articles · won praise 1 · views 3644

Guess you like

Origin blog.csdn.net/qq_40111437/article/details/104789444
Recommended