Java教程

java代理模式

本文主要是介绍java代理模式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

代理模式

指的是使用一个代理对象将原对象包装起来,之后用这个代理来取代该对象,任何对原始对象的调用都需要通过代理。

1. 静态代理

程序运行之前就已经定好代理类和委托类的关系。

BasicSubject.java

/**  
 * 代理接口
 */ 
public interface BasicSubject {
    public void doSomething();
}

BasicImpl.java

/** 
 * 委托类,真正执行任务的类,实现了代理接口
 */ 
public class BasicImpl implements BasicSubject{
    @Override
    public void doSomething() {
        System.out.println("do something!");
    }
}

BasicProxy.java

/** 
 * 代理类,实现了代理接口,同时里面有委托类的对象引用
 */ 
public class BasicProxy implements BasicSubject{
    private BasicImpl basic = new BasicImpl();

    @Override
    public void doSomething() {
        this.before();
        basic.doSomething();
        this.after();
    }

    public void before(){
        System.out.println("before");
    }

    public void after(){
        System.out.println("after");
    }
}

testStaticProxy.java

public class testStaticProxy {
    public static void main(String[] args) {
        BasicSubject basicSubject = new BasicProxy();
        basicSubject.doSomething();
    }
}

可以看出,静态代理类由于一个类只能代理一种类型的对象,因此代码量比较多。同时当接口添加了一个方法时,除了实现类,所有的代理类也要添加改方法的实现,增加了代码维护工作量。

2. 动态代理

动态代理改进了静态代理的一些缺点,主要是编译后动态生成字节码并加载到JVM中进行实现。也被叫做JDK代理

BasicImpl01.java

public class BasicImpl01 implements BasicSubject{
    @Override
    public void doSomething() {
        System.out.println("01 do something!");
    }
}

BasicImpl02.java

public class BasicImpl02 implements BasicSubject{
    @Override
    public void doSomething() {
        System.out.println("02 do something!");
    }
}

DynamicSubjectProxy.java

public class DynamicSubjectProxy implements InvocationHandler {

    private Object ProxyObject;

    public Object newProxyInstance(Object ProxyObject){
        this.ProxyObject = ProxyObject;

        return Proxy.newProxyInstance(
                ProxyObject.getClass().getClassLoader(),
                ProxyObject.getClass().getInterfaces(),
                this
        );
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before do something");
        Object result = method.invoke(ProxyObject, args);
        System.out.println("after do something");
        return result;
    }
}

TestDynamicProxy.java

public class TestDynamicProxy {
    public static void main(String[] args) {
        DynamicSubjectProxy dynamicProxy = new DynamicSubjectProxy();

        BasicImpl01 basicImpl01 = new BasicImpl01();
        BasicImpl02 basicImpl02 = new BasicImpl02();

        BasicSubject basicSubject01 = (BasicSubject) dynamicProxy.newProxyInstance(basicImpl01);
        basicSubject01.doSomething();

        BasicSubject basicSubject02 = (BasicSubject) dynamicProxy.newProxyInstance(basicImpl02);
        basicSubject02.doSomething();
    }
}

动态代理对象不需要实现接口,但是要求目标对象必须实现接口,否则不能使用动态代理。

3. Cglib代理

cglib可以代理没有实现接口的类

使用时需要引入jar包

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

AdminCglibService.java

public class AdminCglibService {
    public void doSomething(){
        System.out.println("do something!");
    }

    public Object returnSomething(){
        System.out.println("return something!");
        return new Object();
    }
}

AdminServiceCglibProxy.java

public class AdminServiceCglibProxy implements MethodInterceptor {
    private Object target;

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

    public Object getProxyInstance(){
        Enhancer en = new Enhancer();

        en.setSuperclass(target.getClass());

        en.setCallback(this);

        return en.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before");
        Object obj = method.invoke(target);
        System.out.println("after");
        return obj;
    }
}

CglibProxyTest.java

public class CglibProxyTest {
    public static void main(String[] args) {
        AdminCglibService target = new AdminCglibService();

        AdminServiceCglibProxy proxyFactory = new AdminServiceCglibProxy(target);

        AdminCglibService proxy = (AdminCglibService) proxyFactory.getProxyInstance();

        Object obj = proxy.returnSomething();

        proxy.doSomething();
    }
}

对比

  1. 静态代理实现比较简单,只需要对对象进行封装,即可实现功能,但是静态代理只能代理一个目标对象,当目标对象过多时,需要重复编写许多代理类。
  2. 动态代理需要目标对象实现业务接口,代理类只需实现InvocationHandler接口。
  3. 静态代理在编译时就产生class字节码文件,效率较高
  4. 动态代理必须实现InvocationHandler接口,通过反射代理方法,比较消耗系统性能,但可以减少代理类的数量,使用更灵活
  5. cglib代理无需实现接口,通过生成类字节码实现代理,比反射稍快,不存在性能问题,但cglib会继承目标对象,需要重写方法,所以目标对象不能为final类
这篇关于java代理模式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!