天天看點

【面試】:阿裡面試官問我設計模式——代理模式,我是這樣回答的!

1.什麼是代理模式? 為對象提供一種代理以控制對這個對象的通路。代理模式相當于:中介或者經紀人 ,代理類可以在被代理類的基礎之上增加功能(擴充功能),比如日志記錄和權限控制 ,這樣被代理類隐藏起來了,比較安全。

1.代理模式實作方式有哪些?

靜态代理和動态代理

2.靜态代理是:需要程式員人為建立好代理類,缺點;如果被代理類很多的話,需要手寫很多個代理類,代碼會變得非常備援。

3.靜态代理實作方式有哪些?

1.通過繼承2.實作接口

1.通過實作接口方式實作靜态代理

1.定義共同接口

package com.mayikt.service;
public interface OrderService {

    /**
     * 共同抽象的方法
     */
    void order();
}
           

2.定義被代理類實作共同的接口

package com.mayikt.service.impl;

import com.mayikt.service.OrderService;

public class OrderServiceImpl implements OrderService {
    public void order() {
        System.out.println("執行訂單業務邏輯代碼");
    }
}
           

3.手寫代理類OrderServiceProxy

package com.mayikt.service.proxy;

import com.mayikt.service.OrderService;
import com.mayikt.service.impl.OrderServiceImpl;
public class OrderServiceProxy implements OrderService {
    /**
     * 被代理對象
     */
    private OrderService orderService;

    public OrderServiceProxy(OrderService orderService) {
       this.orderService = orderService;
    }
    public void order() {
        System.out.println(">>>列印訂單日志開始");
        orderService.order();
        System.out.println(">>>列印訂單日志結束");
    }

}
           

4.測試

package com.mayikt.service;

import com.mayikt.service.cglib.proxy.CglibMethodInterceptor;
import com.mayikt.service.impl.OrderServiceImpl;
import com.mayikt.service.jdk.proxy.JdkInvocationHandler;
import com.mayikt.service.proxy.OrderServiceProxy;
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;

public class Client {
    public static void main(String[] args) {
       OrderService orderService = new OrderServiceProxy(new OrderServiceImpl());
       orderService.order();
    }
}
           

通過繼承的方式實作靜态代理

package com.mayikt.service;
public interface OrderService {

    /**
     * 共同抽象的方法
     */
    void order();
}
           

2.定義被代理類

package com.mayikt.service.impl;

import com.mayikt.service.OrderService;

public class OrderServiceImpl implements  OrderService{
    public void order() {
        System.out.println("執行訂單業務邏輯代碼");
    }
}
           

3.手寫代理類

package com.mayikt.service.proxy;

import com.mayikt.service.OrderService;
import com.mayikt.service.impl.OrderServiceImpl;

public class OrderServiceProxy extends OrderServiceImpl {

    public void order() {
        System.out.println(">>>列印訂單日志開始");
        super.order();// 執行父類的order 方法OrderServiceImpl
        System.out.println(">>>列印訂單日志結束");
    }

}
           

4、測試

package com.mayikt.service;

import com.mayikt.service.cglib.proxy.CglibMethodInterceptor;
import com.mayikt.service.impl.OrderServiceImpl;
import com.mayikt.service.jdk.proxy.JdkInvocationHandler;
import com.mayikt.service.proxy.OrderServiceProxy;
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;

public class Client  {
    public static void main(String[] args) {
        OrderService orderService = new OrderServiceProxy();
        orderService.order();
    }
}
           

動态代理

1.動态代理:不需要關心代理類, jvm運作的時候自動建立代理類,不需要手動建立。

2.動态代理實作方式有哪些?

jdk動态代理和cglib原理

3.jdk動态代理:jdk動态生成的代理類都是實作接口形式,是以被代理類必須實作接口(通過反射的方式實作)

cglib代理:通過asm位元組碼技術實作動态生成代理類,運作時動态的生成一個被代理類的子類

4.jdK動态代理要求被代理的類必須實作接口,當需要被代理的類沒有實作接口時cglib代理是一個很好的選擇

5.spring預設會使用JDK的動态代理,但是如果目标對象沒有實作接口,則預設會采用CGLIB代理;

jdk實作動态代理

package com.mayikt.service;
public interface OrderService {

    /**
     * 共同抽象的方法
     */
    void order();
}
           
package com.mayikt.service.impl;

import com.mayikt.service.OrderService;

public class OrderServiceImpl implements OrderService {
    public void order() {
        System.out.println("執行訂單業務邏輯代碼");
    }
}
           

3.建立生成動态代理類的類:JdkInvocationHandler

package com.mayikt.service.jdk.proxy;

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

public class JdkInvocationHandler implements InvocationHandler {
    /**
     * 被代理類對象 目标代理對象
     */
    private Object target;

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

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //執行方法前列印日志
        System.out.println(">>>jdk列印訂單日志開始:proxy:"+proxy.getClass().toString());
        Object reuslt = method.invoke(target, args);// java的反射機制執行方法 執行目标對象的方法
        //執行方法後列印日志
        System.out.println(">>>jdk列印訂單日志結束");
        return reuslt;
    }

    /**
     * 使用jdk動态代理建立代理類
     *
     * @param <T>
     * @return
     */
    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
}
           
package com.mayikt.service;

import com.mayikt.service.cglib.proxy.CglibMethodInterceptor;
import com.mayikt.service.impl.OrderServiceImpl;
import com.mayikt.service.jdk.proxy.JdkInvocationHandler;
import com.mayikt.service.proxy.OrderServiceProxy;
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;

public class Client  {
    public static void main(String[] args) {
        // 1.使用jdk動态代理
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");//可以動态生成.class檔案
        OrderService proxy = new JdkInvocationHandler(new OrderServiceImpl()).getProxy();
        proxy.order();

    }
}
           

使用cglib實作動态代理

<dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.12</version>
     </dependency>
           
package com.mayikt.service.impl;

import com.mayikt.service.OrderService;

public class OrderServiceImpl {
    public void order() {
        System.out.println("執行訂單業務邏輯代碼");
    }
}
           
package com.mayikt.service.cglib.proxy;

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

import java.lang.reflect.Method;

public class CglibMethodInterceptor implements MethodInterceptor {
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println(">>>>cglib日志收集開始....");
        Object reuslt = proxy.invokeSuper(obj, args);
        System.out.println(">>>>cglib日志收集結束....");
        return reuslt;
    }
}
           
package com.mayikt.service;

import com.mayikt.service.cglib.proxy.CglibMethodInterceptor;
import com.mayikt.service.impl.OrderServiceImpl;
import com.mayikt.service.jdk.proxy.JdkInvocationHandler;
import com.mayikt.service.proxy.OrderServiceProxy;
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;

public class Client  {
    public static void main(String[] args) {
        // 使用cglib動态代理
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");//可以動态生成class檔案
        CglibMethodInterceptor cglibMethodInterceptor = new CglibMethodInterceptor();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(OrderServiceImpl.class);
        enhancer.setCallback(cglibMethodInterceptor);
        OrderServiceImpl orderServiceImpl = (OrderServiceImpl) enhancer.create();
        orderServiceImpl.order();

    }
}
           

總結:看完有什麼不懂的話歡迎在下方留言評論,記得點個贊哦!