Java设计模式--代理模式+动态代理+CGLib代理

静态代理

抽象主题角色:声明真实主题和代理主题的共同接口。程序员

代理主题角色:代理主题内部含有对真实主题的引用,从而在任什么时候候操做真实主题对象;代理主题提供一个与真实主题相同的接口,以便在任什么时候候均可以代替真实主题。代理角色一般在将客户端调用传递给真实的主题以前或以后,都要执行某个操做,而不是单纯的传递调用。面试

真实主题角色:定义代理角色所表明的的真实对象。mybatis

UML图:ide

抽象主题post

public interface Subject {
    void request();
}

 

真实主题this

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("真实对象的方法");
    }
}

 

代理主题spa

public class ProxySubject implements Subject {

    private RealSubject subject;

    public ProxySubject() {
    }

    @Override
    public void request() {
        pre();
        if (subject == null){
            subject = new RealSubject();
        }
        subject.request();
        post();
    }

    private void pre(){
        System.out.println("方法执行以前");
    }

    private void post(){
        System.out.println("方法执行以后");
    }
}

 

执行:设计

    public static void main(String[] args) throws Exception {
        ProxySubject subject = new ProxySubject();
        subject.request();
    }

 

输出:代理

方法执行以前
真实对象的方法
方法执行以后 

动态代理

JDK自带的动态代理,实现InvocationHandler接口。code

声明接口

public interface MyConnection extends AutoCloseable {

    void createStatement() throws Exception;

    @Override
    void close() throws Exception;
}

 

真实主题

public class MyDefaultConnection implements MyConnection {
    @Override
    public void createStatement() throws Exception {
        System.out.println("Create Statement ...");
    }

    @Override
    public void close() throws Exception {
        System.out.println("Close Connection ...");
    }
}

 

代理主题

public class MyConnectionProxy implements InvocationHandler {

    private MyConnection conn;
    private MyConnection proxyConn;

    public MyConnectionProxy(MyConnection conn) {
        this.conn = conn;
        this.proxyConn = (MyConnection) Proxy.newProxyInstance(MyConnection.class.getClassLoader(), new Class<?>[] {MyConnection.class}, this);
    }

    public MyConnection getConn() {
        return conn;
    }

    public MyConnection getProxyConn() {
        return proxyConn;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        System.out.println("==代理方法:" + methodName);
        if("close".equals(methodName)){
            System.out.println("**不执行close方法");
        }else{
            return method.invoke(conn, args);
        }
        return null;
    }
}

 

执行:

    public static void main(String[] args) throws Exception {
        MyConnection connection = new MyDefaultConnection();
        MyConnectionProxy proxy = new MyConnectionProxy(connection);
        proxy.getProxyConn().createStatement();
        proxy.getProxyConn().close();
    }

 

你会发现个人代理对象去哪里了?实际上我放在InvocationHandler的实现类里面了,这里参考的是mybatis源码的设计。

输出:

==代理方法:createStatement
Create Statement ...
==代理方法:close
**不执行close方法

CGLib

面试的时候可能问你:JDK动态代理和CGLib的区别是什么,说的最多的就是JDK须要一个接口,而CHLib不须要接口就能实现动态代理。

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.12</version>
</dependency>

 

须要代理的对象

public class Programmer {

    public void work(){
        System.out.println("程序员正在敲代码...");
    }

    public final void finalCannotOverride(){
        System.out.println("final方法不能被生成的子类覆盖");
    }

    private void privateCannotOverride(){
        System.out.println("private方法不能被生成的子类覆盖");
    }
}

 

代理类

public class ProgrammerProxy implements MethodInterceptor {

    // 真实对象
    private Object realObject;
    // 代理对象
    private Object proxyObject;

    public ProgrammerProxy(Object realObject) {
        this.realObject = realObject;
        Enhancer enhancer = new Enhancer();
        // 设置须要代理的对象
        enhancer.setSuperclass(realObject.getClass());
        // 设置代理人
        enhancer.setCallback(this);
        this.proxyObject = enhancer.create();
    }

    public Programmer getProxyObject() {
        return (Programmer) proxyObject;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        pre();
        Object result = method.invoke(realObject, objects);
        post();
        return result;
    }

    private void pre(){
        System.out.println("==先吃早餐");
    }

    private void post(){
        System.out.println("==下班打卡");
    }
}

 

执行:

    public static void main(String[] args) throws Exception {
        Programmer programmer = new Programmer();
        ProgrammerProxy proxy = new ProgrammerProxy(programmer);
        proxy.getProxyObject().finalCannotOverride();
        proxy.getProxyObject().work();
    }

 

输出:

final方法不能被生成的子类覆盖
==先吃早餐
程序员正在敲代码...
==下班打卡