代理模式

代理模式:为某些对象提供代理以实现对这个对象的访问。

对一个对象进行访问控制的原因是为了只有在我们确实需要这个对象时才对它进行创建和初始化。

一般包括以下组件:

被代理者接口:提供被代理者的访问途径。

被代理者:定义真实对象。

代理者:保存一个被代理者的引用, 并对外提供统一的代理方法, 可以对被代理者的方法实现修饰和控制。

 

要生成某一个对象的代理对象,这个代理对象通常也要编写一个类来生成,所以首先要编写用于生成代理对象的类。java在JDK1.5之后提供了java.lang.reflect.Proxy类,通过Proxy类提供的newProxyInstance方法用来创建一个对象的代理对象,这个方法总共有3个参数,ClassLoader loader用来指明生成代理对象使用哪个类装载器,Class<?>[] interfaces用来指明生成哪个对象的代理对象,通过接口指定,InvocationHandler 用来指明产生的这个代理对象要做什么事情。所以只需要调用newProxyInstance方法就可以得到某一个对象的代理对象了。

代理类需要实现InvocationHandler接口,该接口只有一个invoke方法,用于自定义代理行为. 

JDK动态代理示例

----------------

//代理接口
public interface IClient {
    void doSomething(String thing);
}

-

//被代理者
public class Client implements IClient {
    @Override
    public void doSomething(String thing) {
        System.out.println("do a thing:" + thing);
    }
}

-

//代理
public class ProxyAgent implements InvocationHandler {
    private Object client;
    
    public ProxyAgent(Object client) {
        this.client = client;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 这里可以对method进行过滤或添加其他代码,然后调具体对象的方法
        Object object = method.invoke(client, args);
        return object;
    }
    
    //获取代理实例 
    public Object getProxy(){
        return Proxy.newProxyInstance(getClass().getClassLoader(), client.getClass().getInterfaces(), this);
    }
    
    public static void main(String[] args){
        //被代理者
        Client client = new Client();
        //代理者
        IClient proxy = (IClient) new ProxyAgent(client).getProxy();
        //调用代理动作
        proxy.doSomething("buy something");
    }
}

----------------

由上可见,使用JDK的Proxy实现动态代理有一个要求:被代理的类必须实现接口,未实现接口则没办法完成动态代理。

 

实际中有些类没有实现接口,不应该为了实现动态代理而去抽出一些没有实例意义的接口,可以通过cglib对一个类实现代理。

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

 

示例如下:

package cn.luan.demo;

import java.lang.reflect.Method;

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

/*
 * 动态代理类
 */
public class DynamicProxy implements MethodInterceptor {

    // 被代理对象
    Object targetObject;

    // 动态生成一个新的类,使用父类的无参构造方法创建一个指定了特定回调的代理实例
    public Object getProxyObject(Object object) {
        //set被代理对象
        this.targetObject = object;
        //动态代码生成器
        Enhancer enhancer=new Enhancer();
        //回调方法
        enhancer.setCallback(this);
        //设置生成类的父类类型
        enhancer.setSuperclass(targetObject.getClass());
        //动态生成字节码并返回代理对象
        return enhancer.create();
    }

    // 实现了一个方法拦截器接口
    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

        System.out.println("方法调用前织入的横切内容");
        System.out.println("method name: " + method.getName());

        // 调用方法
        Object result = methodProxy.invoke(targetObject, args);

        System.out.println("方法调用后织入的横切内容");

        return result;
    }

    //测试
    public static void main(String[] args) {
        Client client = (Client) new DynamicProxy().getProxyObject(new Client());
        client.doSomething("cglib proxy");
    }
}

--cglib不能对final类做代理

 

 

end

转载于:https://www.cnblogs.com/luangeng/p/5517307.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值