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

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

一般包括以下组件:

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

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

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

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

Java动态代理 cglib的更多相关文章

  1. Java动态代理--CGLib实现

    上一篇说了通过JDK实现实现了动态代理,但是用JDK实现代理,要求所代理的类必须实现一个接口.如果我们类不实现接口,这就在无法使用JDK提供的Proxy来实现动态代理,这个时候我们应该怎么办呢?我们找 ...

  2. [转]java动态代理(JDK和cglib)

    转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html java动态代理(JDK和cglib) JAVA的动态代理 代理模式 代理 ...

  3. Java静态代理&动态代理&Cglib代理详解

    一.静态代理 根据被代理的类的时机的不同,如果在编译阶段就能确定下来的被代理的类是哪一个,那么,就可以使用静态代理的方式. 申明一个接口: /** * @author jiaqing.xu@hand- ...

  4. CGLIB和Java动态代理的区别(笔记)

    java常用知识点: 1.Java动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为Proxy,Java类继承机制不允许多重继承):CGLIB能够代理普通类:2.Jav ...

  5. Java动态代理与CGLib

    Java帝国之动态代理 CGLib:从兄弟到父子-动态代理在民间是怎么玩的? 以上两篇文章引用自微信公众号: 码农翻身 Java动态代理 深度详解 以上文章引用博客园:陈树义

  6. Java动态代理(三)——Cglib动态代理

    一.Cglib动态代理Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用Cglib即使代理类没有实现任何接口也可以实现动态代理功能.而且,它的运行速度要远远快 ...

  7. java动态代理(JDK和CGLIB)笔记

    动态代理:为一堆interface或类的实现提供统一的执行通道,从含义上就像局域网电脑通过代理上网一样,走统一的通道,代理控制通道,自然可以在通道里加上自定义实现,例如像AOP切面,日志等. JDK的 ...

  8. Java动态代理全面分析

    代理模式 解说:给某一个对象提供一个代理,并由代理对象控制对原对象的引用: 代理模式需要以下几个角色: 1  主题:规定代理类和真实对象共同对外暴露的接口: 2  代理类:专门代理真实对象的类: 3 ...

  9. Java 动态代理作用是什么?

    Java 动态代理作用是什么?   1 条评论 分享   默认排序按时间排序 19 个回答 133赞同反对,不会显示你的姓名 Intopass 程序员,近期沉迷于动漫ING 133 人赞同 ① 首先你 ...

随机推荐

  1. 卸载了mysql之后,mysql服务仍在,显示读取描述失败,错误代码2

    卸载了mysql之后,mysql服务仍在,显示读取描述失败,错误代码2 用360软件管家,卸载mysql5.5,卸载了mysql之后,再依次删除 mysql的安装目录.c盘下的隐藏文件夹Program ...

  2. spark使用Hive表操作

    spark Hive表操作 之前很长一段时间是通过hiveServer操作Hive表的,一旦hiveServer宕掉就无法进行操作. 比如说一个修改表分区的操作 一.使用HiveServer的方式 v ...

  3. 夺命雷公狗---DEDECMS----1dedecms的安装过程

    我们这次要玩的dedecms(cms也就是内容管理系统),电商网.或者政府网..小说网.新闻网之类的都是基于可以用cms来实现的. 现在在市场上主流的cms系统有dedecms(织梦),帝国cms,p ...

  4. 使用java访问 动态链接库(dll)

    在这个时候,我们可以使用的java技术有jni.jna.jnative,这个大部分都可以完成任务.但是有时候我们在实际情况中拿到的dll有变化,当我们需要用的函数是在dll中的类里面的话,我们再使用前 ...

  5. 【crunch bang】 tint2-用来控制桌面的布局

    tint2配置: #--------------------------------------------- # TINT2 CONFIG FILE #----------------------- ...

  6. 锋利的JQuery(六)

    $.ajax():可以设定beforeSend.error.success.complete等 $.getScript():加载JS文件 $.getJSON():加载JSON文件 $.each():通 ...

  7. Tomcat内存溢出解决办法

    使用Java程序从数据库中查询大量的数据时出现异常:java.lang.OutOfMemoryError: Java heap space在JVM中如果98%的时间是用于GC且可用的 Heap siz ...

  8. android 项目学习随笔一(闪屏 )

    1.取标题栏且全屏 <activity android:name="com.ecollab.zhsh66.SplashActivity" android:label=&quo ...

  9. Unexpected error: UnicodeDecodeError: 'ascii' codec can't decode byte 0xd2 in position 69: ordinal not in range(128)-解决办法

  10. LUA笔记之字符串

    LUA提供了自动数值转换, 基本上说是乱来也不为过, 就当做是不熟悉数据结构吧, 例子: print("10" + 1) --> 11 print("10 + 1& ...