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

java

静态代理

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

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

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

UML图:

抽象主题

public interface Subject {

void request();

}

真实主题

public class RealSubject implements Subject {

@Override

public void request() {

System.out.println("真实对象的方法");

}

}

代理主题

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接口。

声明接口

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

CGLib不需要接口就能实现动态代理。

CGLIB 原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。

CGLIB 底层:使用字节码处理框架ASM,来转换字节码并生成新的类。

<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方法不能被生成的子类覆盖

==先吃早餐

程序员正在敲代码...

==下班打卡

以上是 Java设计模式--代理模式+动态代理+CGLib代理 的全部内容, 来源链接: utcz.com/z/392692.html

回到顶部