一、如何理解代理技术

Proxy:不用你去做,别人代替你去处理。如Windows快捷方式,又如房屋中介

起到一个中介作用,通过代理对象,可以去掉客户不能看到的内容和服务或者添加客户需要的额外服务。

二、代理模式

代理模式使用代理对象完成用户请求,屏蔽用户对真实对象的访问。现实世界的代理人被授权执行当事人的一些事宜,无需当事人出面,从第三方的角度看,似乎当事人并不存在,因为他只和代理人通信。

而事实上代理人是要有当事人的授权,并且在核心问题上还需要请示当事人。

在软件设计中,使用代理模式的意图也很多,比如因为安全原因需要屏蔽客户端直接访问真实对象,或者在远程调用中需要使用代理类处理远程方法调用的技术细节 (如 RMI),

也可能为了提升系统性能,对真实对象进行封装,从而达到延迟加载的目的。

代理模式角色分为 4 种:

1.主题接口:定义代理类和真实主题的公共对外方法,也是代理类代理真实主题的方法;

2.真实主题:真正实现业务逻辑的类;

3.代理类:用来代理和封装真实主题;

4.Main:客户端,使用代理类和主题接口完成一些工作。

三、具体使用

1.静态代理

/**
* Created by solverpeng on 2016/6/29.
*/
public interface Factory { void say(); void produce(); }

Factory

/**
* NikeFatory
*
* @author solverpeng
* @create 2016-06-29-11:28
*/
public class NikeFactory implements Factory {
@Override
public void say() {
System.out.println("我要开始生产了!");
} @Override
public void produce() {
System.out.println("正在生产Nike衣服!");
}
}

NikeFactory

/**
* NikeFactoryProxy
*
* @author solverpeng
* @create 2016-06-29-11:30
*/
public class NikeFactoryProxy implements Factory {
private NikeFactory nikeFactory; public NikeFactoryProxy() {
this.nikeFactory = new NikeFactory();
}
@Override
public void say() {
before();
nikeFactory.say();
after();
} @Override
public void produce() {
before();
nikeFactory.produce();
after();
} private void after() {
System.out.println("大家做的不错!");
} private void before() {
System.out.println("在正式开始生产之前,我要说两句!");
}
}

NikeFactoryProxy

@Test
public void testStaticProxy() {
NikeFactoryProxy nikeFactoryProxy = new NikeFactoryProxy();
nikeFactoryProxy.say();
nikeFactoryProxy.produce();
}

testStaticProxy

2.JDK动态代理

@Test
public void testJDKProxy() {
Factory proxyInstance = (Factory) Proxy.newProxyInstance(NikeFactory.class.getClassLoader(), NikeFactory.class.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(NikeFactory.class.newInstance(), args);
}
});
proxyInstance.say();
proxyInstance.produce();
}

testJDKProxy

/**
* 通用的代理生产工厂
*
* @author solverpeng
* @create 2016-06-29-11:45
*/
public class DynamicProxy implements InvocationHandler { private Object target; public DynamicProxy(Object target) {
this.target = target;
} @SuppressWarnings("unchecked")
public <T> T getProxy() {
return (T)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(target, args);
} }

DynamicProxy

@Test
public void testJDKProxy2() {
DynamicProxy dynamicProxy = new DynamicProxy(new NikeFactory());
Factory proxy = dynamicProxy.getProxy();
proxy.say();
proxy.produce();
}

testJDKProxy2

3.CGLIB动态代理(需要额外导入cglib包)

/**
* CglibProxy
*
* @author solverpeng
* @create 2016-06-29-14:40
*/
public class CglibProxy implements MethodInterceptor{
private static CglibProxy instance = new CglibProxy(); public CglibProxy() {
} public static CglibProxy getInstance() {
return instance;
} @SuppressWarnings("unchecked")
public <T> T getProxy(Class<T> cls) {
return (T)Enhancer.create(cls, this);
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(o, objects);
}
}

CglibProxy

@Test
public void testCglibProxy2() {
NikeFactory proxy = CglibProxy.getInstance().getProxy(NikeFactory.class);
proxy.say();
proxy.produce();
}

testCglibProxy2

四、总结

JDK动态代理获取代理的是通过:Proxy.newProxyInstance() 方法来获取的,需要一个 InvocationHandler 类型的对象。传入的参数为目标对象。

CGLIB 动态代理获取代理是通过:Enhancer.create() 方法,需要一个 MethodInterceptor 类型的对象。

在使用 CGLIB 包的时候,可能会出现 java.lang.ClassNotFoundException: org.objectweb.asm.Type 的异常,导入 spring 下的 cglib 包就ok。

AOP——代理技术的更多相关文章

  1. Spring AOP 和 动态代理技术

    AOP 是什么东西 首先来说 AOP 并不是 Spring 框架的核心技术之一,AOP 全称 Aspect Orient Programming,即面向切面的编程.其要解决的问题就是在不改变源代码的情 ...

  2. Spring AOP高级——源码实现(1)动态代理技术

    在正式进入Spring AOP的源码实现前,我们需要准备一定的基础也就是面向切面编程的核心——动态代理. 动态代理实际上也是一种结构型的设计模式,JDK中已经为我们准备好了这种设计模式,不过这种JDK ...

  3. Java基础---Java---基础加强---类加载器、委托机制、AOP、 动态代理技术、让动态生成的类成为目标类的代理、实现Spring可配置的AOP框架

    类加载器 Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader 类加载器也是Jav ...

  4. 004-搭建框架-实现AOP机制【一】代理技术

    前景提要 监控方法性能.执行时间.记录日志等 AOP( Aspect Oriented Programming)面向方面编程. 在AOP中,需要定义一个Aspect(切面)类来编写需要横切业务的逻辑代 ...

  5. PHP开发模式之代理技术

    在实际开发中,我们经常要调用第三方的类库如SOAP服务等.使用这些第三方 组件并不难,最麻烦的莫过于调用了,一般的调试手段最方便的莫过于记日志了. 示例: 假如有以下第三方类库. // filenam ...

  6. JAVA中的代理技术(静态代理和动态代理)

    最近看书,有两个地方提到了动态代理,一是在Head First中的代理模式,二是Spring AOP中的AOP.所以有必要补充一下动态代理的相关知识. Spring采用JDK动态代理和CGLib动态代 ...

  7. Java中动态代理技术生成的类与原始类的区别 (转)

    用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑. 平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道它是把类重新生成了一遍,在切面上加上了后 ...

  8. Java中动态代理技术生成的类与原始类的区别

    用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑. 平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道它是把类重新生成了一遍,在切面上加上了后 ...

  9. Spring-java代理技术总结

    Spring 中采用JDk的动态代理和CGLib代理技术在运行期间织入增强,所以用户不需要装备特殊的编译器或者类装载器就可以使用AOP功能. 要使用jdk的动态代理,目标类必须实现接口,而CGLib代 ...

随机推荐

  1. supervisor监控gearman任务

    安装supervisor方法,可以直接用 yum install supervisord ,但是版本可能会旧一点,可以参考官方的方法: easy_install supervisor http://s ...

  2. (String) | String.valueOf()

    Map m = new HashMap(); Integer i = 5; String s = null; m.put("val1", i); m.put("val2& ...

  3. IDE、SATA、SCSI、SAS、FC、SSD硬盘类型介绍[zz]

    目前所能见到的硬盘接口类型主要有IDE.SATA.SCSI.SAS.FC等等. IDE是俗称的并口,SATA是俗称的串口,这两种硬盘是个人电脑和低端服务器常见的硬盘.SCSI是"小型计算机系 ...

  4. 用飞信监控GoldenGate进程

    监控GoldenGate进程 1)         在goldengate安装目录下建立文件ogginfo $vim ogginfo  info all 2)         配置飞信报警       ...

  5. 使用 ContentProviderOperation 来提升性能

    ContentProviders  是android 系统核心组件之一,ContentProviders 封装了数据的访问接口,其底层数据一般都是保存在数据库中或者保存在云端. 有时候你需要更新多行数 ...

  6. Django 源码小剖: 更高效的 URL 调度器(URL dispatcher)

    效率问题 django 内部的 url 调度机制说白了就是给一张有关匹配信息的表, 这张表中有着 url -> action 的映射, 当请求到来的时候, 一个一个(遍历)去匹配. 中, 则调用 ...

  7. Quartz 2D绘制简单图形

    在Quartz 2D中,绘图是通过图形上下文进行绘制的,以下绘制几个简单的图形 首先先创建一个QuartzView.swift文件继承自UIView,然后实现drawRect方法: import UI ...

  8. Myeclipse设置JAVA选中高亮显示

    1.打开显示功能 选择Windows->Preferences->Java-> Editor-> Mark Occurrences ,勾选选项.这时,当你单击一个元素的时候,代 ...

  9. C#下水晶报表打印自定义纸张

    在VB6中,如果要自定义纸张很方便:  Rpt.PaperSize = crPaperUser  Rpt.SetUserPaperSize lZZG, lZZK 但在C#中却不行了,没有发现 SetU ...

  10. 循环a数组(值代表b的下标)删除b数组中存在的记录,从后往前删

    for (var j = adelete.Count-1; j >= 0; --j)                     {                         aAttachm ...