設計模式之代理模式(下) CGLIB動態代理

CGLIB動態代理

  • CGLIB動態代理很是強大、性能還挺厲害(點這裏查看JDK與CGLIB的性能對比(引用))。
  • 它的主要原理是:CGLIB經過字節碼技術動態的生成業務類的子類,覆蓋業務類的方法。並進行代理,由於採用的是繼承方式,因此沒法使用對final修飾的類進行代理。

光看原理確定仍是不是那麼瞭解的,因此咱們仍是來寫代碼吧!html

首先編寫一個業務類java

/**
 * 人員信息服務
 * @author wushuaiping
 * @date 2018/3/14 下午10:44
 */
public class EmployeeServiceImpl {
    public void insert(Employee employee){
        System.out.println("我調用了業務方法往數據庫插入了一條數據~");
    }
}

再編寫CGLIB動態代理的代碼數據庫

  1. 首先須要去實現MethodInterceptor 方法攔截器。提供了intercept,方便在目標方法上進行切入。
  2. 再寫一個獲取代理對象的方法,該方法中須要使用到Enhancer,CGLIB經過該加強器底層的字節碼技術生成業務類的子類。並建立該子類的對象。 除了經過enhancer.create()經過無參構造器建立業務類代理對象之外;還可使用enhancer.create(Class[] argumentTypes, Object[] arguments)經過有參構造器來建立對象。具體方式請點擊(引用)
/**
 *  CGLIB動態代理
 * @author wushuaiping
 * @date 2018/3/14 下午10:50
 */
public class CGLIBProxy implements MethodInterceptor{

    private Object target;

    public Object newInstance(Object object){
        this.target = object;
        // 加強器
        Enhancer enhancer = new Enhancer();
        /* 生成被代理業務類(EmployeeServiceImpl)的子類;
         * 就是由於這裏繼承的關係,被代理業務類就不能使用final修飾。
         */
        enhancer.setSuperclass(this.target.getClass());
        // 被代理業務類全部方法都會經過這裏來調用
        enhancer.setCallback(this);
        // 建立代理對象 這個是建立無參構造器代理對象的方式
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        before();
        // 去調用父類中的方法
        methodProxy.invokeSuper(o, objects);
        after();
        return null;
    }

    private void before(){
        System.out.println("操做前的日誌記錄~~");
    }

    private void after(){
        System.out.println("操做後的日誌記錄~~");
    }
}

Test caseide

  1. 前後建立代理對象以及被代理的業務類對象
  2. 而後使用代理對象調用newInstance獲取業務類代理類的對象。
  3. 調用業務類代理對象的業務方法
public static void main(String[] args) {
        CGLIBProxy proxy = new CGLIBProxy();
        EmployeeServiceImpl employeeService = new EmployeeServiceImpl();
        EmployeeServiceImpl proxySer = (EmployeeServiceImpl)proxy.newInstance(employeeService);
        proxySer.insert(new Employee());
    }

運行結果性能

操做前的日誌記錄~~
我調用了業務方法往數據庫插入了一條數據~
操做後的日誌記錄~~

來說講優缺點吧:

  • CGLIB的功能仍是蠻強大的,能夠不用實現接口也可進行動態代理。可是缺點也很明顯,由於底層經過繼承業務類的方式來進行代理,因此業務類不能使用final修飾。
相關文章
相關標籤/搜索