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

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

一般包括以下组件:

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

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

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

要生成某一个对象的代理对象,这个代理对象通常也要编写一个类来生成,所以首先要编写用于生成代理对象的类。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

最新文章

  1. C#与Java对比学习:类型判断、类与接口继承、代码规范与编码习惯、常量定义
  2. .net 将List序列化成Json字符串
  3. c#-1 数据结构 定义相关 界面交互数据 Model层
  4. SQL Server求解最近多少销售记录的销售额占比总销售额的指定比例
  5. 第一个Sprint冲刺第九天
  6. Java的外部类和内部类+静态变量和非静态变量的组合关系
  7. linux 捕获信号处理中遇到的死锁
  8. [cocos2d demo]新科娘收集水表
  9. IE6下a标签上发送ajax请求总是error
  10. 转换器5:参考Python源码,实现Php代码转Ast并直接运行
  11. C# Coding Conventions(译)
  12. java @Service 引入什么包
  13. [ZJOI2012]波浪
  14. [项目实践] 在项目实战中提升代码效率的的一次应用实践-----使用列表解析式输出当前android设备的CPU核数
  15. HTML和CSS中判断IE版本并实现相应HTML和CSS
  16. sqlserver创建数据库
  17. Android 基础 (四大组件,五大存储,六大布局)
  18. [转]MVC 分页
  19. FactoryBean
  20. Tmux 的常用命令详解

热门文章

  1. paper 74:MATLAB图像处理_HSV与RGB颜色空间互转
  2. sql server 2008 安装过程与创建建sql server登录用户
  3. 文字处理TX Text Control X10独家揭秘(二):图像占位符合并
  4. android 应用架构随笔三(ListView)
  5. django templates学习使用记录
  6. 在CentOS 6 32/64 上安装 PPTP 方式 VPN 服务
  7. 为 Macbook 安装 wget 命令
  8. innodb buffer pool flush机制
  9. uboot启动参数
  10. spring.xml命名空间