JAVA 代理实现

代理的实现分动态代理和静态代理,静态代理的实现是对已经生成了的JAVA类进行封装。

动态代理则是在运行时生成了相关代理累,在JAVA中生成动态代理一般有两种方式。

JDK自带实现方法

JDK实现代理生成,是用类 java.lang.reflect.Proxy, 实现方式如下

EX:

public class JDKProxy {

public static Object getPoxyObject(final Object c) {

return Proxy.newProxyInstance(c.getClass().getClassLoader(), c.getClass().getInterfaces(),// JDK实现动态代理,但JDK实现必须需要接口

new InvocationHandler() {

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

// TODO Auto-generated method stub

Object reObj = null;

System.out.print("you say: ");

reObj = method.invoke(c, args);

System.out.println(" [" + Calendar.getInstance().get(Calendar.HOUR) + ":"

+ Calendar.getInstance().get(Calendar.MINUTE) + " "

+ Calendar.getInstance().get(Calendar.SECOND) + "]");

return reObj;

}

});

}

}

测试代理类方法

public class TestForPoxy {

public static void main(String[] args) {

ServiceTest service = new ServiceTestImpl();

System.out.println(service.getClass().getSimpleName());

ServiceTest poxyService = (ServiceTest) JDKProxy.getPoxyObject(service);

System.out.println(poxyService.getClass().getSuperclass());

poxyService.saySomething("hello,My QQ code is 107966750.");

poxyService.saySomething("what 's your name?");

poxyService.saySomething("only for test,hehe.");

}

}

1, Proxy实现代理的目标类必须有实现接口

2, 生成出来的代理类为接口实现类,和目标类不能进行转换,只能转为接口实现类进行调用

明显特点:通过此方法生成出来的类名叫做 $Proxy0

用CGLIB包实现

CGLIB是一个开源项目,官方网址是:http://cglib.sourceforge.net/,可以去上面下载最新JAR包,

本项目用的是cglib-3.0.jar

本项目还加入了依赖JAR包asm-4.0.jar,asm-util-4.0.jar

实现方式如下

EX:

public class CGLIBProxy {

public static Object getPoxyObject(Object c) {

Enhancer enhancer = new Enhancer();

enhancer.setSuperclass(c.getClass());

enhancer.setCallback(new MethodInterceptor() {

public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable {

System.out.print("you say: ");

proxy.invokeSuper(arg0, arg2);

System.out.println(" [" + Calendar.getInstance().get(Calendar.HOUR) + ":"

+ Calendar.getInstance().get(Calendar.MINUTE) + " " + Calendar.getInstance().get(Calendar.SECOND)

+ "]");

return null;

}

});

return enhancer.create();

}

}

测试代理类方法

public class TestForPoxy {

public static void main(String[] args) {

ServiceTest service = new ServiceTestImpl();

System.out.println(service.getClass().getSimpleName());

//          ServiceTest poxyService = (ServiceTest) JDKProxy.getPoxyObject(service);

ServiceTest poxyService = (ServiceTest) CGLIBProxy.getPoxyObject(service);

System.out.println(poxyService.getClass().getSuperclass());

poxyService.saySomething("hello,My QQ code is 107966750.");

poxyService.saySomething("what 's your name?");

poxyService.saySomething("only for test,hehe.");

}

}

1, CGLIB实现方式是对代理的目标类进行继承

2, 生成出了的代理类可以没方法,生成出来的类可以直接转换成目标类或目标类实现接口的实现类,因JAVA向上转换

明显特点:通过输出看出,看出生成出的代理类的parent类为代理的目标类

Spring  AOP的代理类机制分析

在spring中,bean都是由动态代理生成出来的,那么到底是用JDK的Proxy类实现呢,还是用CGLIB方式实现呢。

AOP  Spring需要的依赖JAR包有:

spring-asm-3.2.0.M1.jar

spring-beans-3.2.0.M1.jar

spring-context-3.2.0.M1.jar

spring-core-3.2.0.M1.jar

spring-expression-3.2.0.M1.jar

spring-aop-3.2.0.M1.jar

spring-aspects-3.2.0.M1.jar

commons\commons-logging-1.1.1\commons-logging-1.1.1.jar

aopalliance\aopalliance.jar

lib\aspectjweaver.jar

实现AOP

先简单的实现AOP

配置如下

<?xml version="1.0" encoding="utf-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"

xsi:schemaLocation="

      http://www.springframework.org/schema/beans

      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

      http://www.springframework.org/schema/aop 

    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

<bean id="test" class="org.ben.spring.service.Test" />

<bean id="aspectBean" class="org.ben.spring.TestAspect" />

<!-- 对Test类进行AOP拦截 -->

<aop:config>

<aop:aspect id="TestAspect" ref="aspectBean">

<!--配置切面-->

<aop:pointcut id="businessService"

expression="execution(* org.ben.spring.service.Test.say(..))" />

<aop:before pointcut-ref="businessService" method="doBefore" />

<aop:after pointcut-ref="businessService" method="doAfter" />

</aop:aspect>

</aop:config>

</beans>

然后进行运行结果如下,表示AOP拦截成功

AOP测试类

public class TestBeans {

public static void main(String[] args) {

ApplicationContext ctx = new ClassPathXmlApplicationContext("test.xml");

Test test=(Test) ctx.getBean("test");

System.out.println(test.getClass().getSimpleName());

test.say();

}

}

输出:

do something in befor

welcome for test

do something in after

打印代理类的生成方式

第一种情况, Test不实现任何接口,代码如下

public class Test {

public void say() {

System.out.println("welcome for test,My QQ is 107966750");

}

}

在TestBeans中加入打印当前对象的名称

如下:

ApplicationContext ctx = new ClassPathXmlApplicationContext("test.xml");

Test test=(Test) ctx.getBean("test");

System.out.println(test.getClass().getSimpleName());

test.say();

输出:

Test$$EnhancerByCGLIB$$4791b36c

super class is class org.ben.spring.service.Test

do something in befor

welcome for test

do something in after

明显看到用了AOP之后,输出的是代理类对象Test$$EnhancerByCGLIB$$bb9b6a7c.而且它的父类是我们的代理目标类。说明是有CGLIB生成的

第二种情况

 

XML的配置不变,改变代理目标类Test的实现方法,如下

public class Test implements TestInter{

public void say() {

System.out.println("welcome for test,My QQ is 107966750");

}

}

和原来不同的是多继承了一个接口,接口中定义了say()方法

在TestBeans中加入打印当前对象的名称

如下:

ApplicationContext ctx = new ClassPathXmlApplicationContext("test.xml");

TestInter test=(TestInter) ctx.getBean("test");

System.out.println(test.getClass().getSimpleName());

System.out.println("super class is "+test.getClass().getSuperclass());

test.say();

输出:

$Proxy0

super class is class java.lang.reflect.Proxy

do something in befor

welcome for test,My QQ is 107966750

do something in after

结论

Spring AOP中,当拦截对象实现了接口时,生成方式是用JDK的Proxy类。当没有实现任何接口时用的是GCLIB开源项目生成的拦截类的子类.

转:http://www.cnblogs.com/springsource/archive/2012/08/30/2664050.html

[转]JAVA的动态代理机制及Spring的实现方式的更多相关文章

  1. Spring学习(二)—— java的动态代理机制

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  2. java的动态代理机制详解

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  3. Java的动态代理机制详解(转)

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  4. (转)java的动态代理机制详解

    原文出自:http://www.cnblogs.com/xiaoluo501395377/p/3383130.html 在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一 ...

  5. [转载] java的动态代理机制详解

    转载自http://www.cnblogs.com/xiaoluo501395377/p/3383130.html 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代 ...

  6. 【转】java的动态代理机制详解

    java的动态代理机制详解   在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们 ...

  7. java的动态代理机制

    前几天看到java的动态代理机制,不知道是啥玩意,然后看了看.死活不知道 invoke(Object proxy, Method m, Object[] args)种的proxy是个什么东西,放在这里 ...

  8. java的动态代理机制详解-----https://www.cnblogs.com/xiaoluo501395377/p/3383130.html

    java的动态代理机制详解-----https://www.cnblogs.com/xiaoluo501395377/p/3383130.html

  9. Java 动态代理机制详解

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

随机推荐

  1. Wpf学习之路……

    Wpf学习之路-- Wpf是 .net中一门做winform的技术,和传统的winform的区别在于: 1.         原来的winform就是拖控件,而wpf的控件都死自己拿标记语言(xaml ...

  2. Myeclipse8.5开发-插件安装二:安装findbugs方法

    环境:Myeclipse8.5 step 1:首先从官网下载findbugs插件:http://downloads.sourceforge.net/project/findbugs/findbugs% ...

  3. JavaScript之作用域与闭包总结

    博主最开始接触程序是C语言,C++,后来是java,现在是php,无论哪一种语言与javascript在机制上都还是有比较大的区别. 下面总结一下用面向对象的思想写javascript需要区分的要点: ...

  4. (iOS)关于zbar扫描条形码,所搭载的设备

    四个月之前写的,现在发出来. 最近在开发一款程序的时候,功能要求扫描条形码. 现在最流行的扫描条形码的开源代码有zbar和zxing两种,可以支持多种一维和二维码. 之前了解过zbar,所以这次试用z ...

  5. DataTable源码分析(二)

    DataTable源码分析(二) ===================== DataTable函数分析 ---------------- DataTable作为整个插件的入口,完成了整个表格的数据初 ...

  6. 关于Form表单一些基础知识

    1.两个重要属性: action:表单需要提交的服务器地址 method:表单提交数据使用的方法,get/post >>>get和post的区别 ①get传参使用URL传递,所有参数 ...

  7. Azure WAF防火墙工作原理分析和配置向导

    Azure WAF工作原理分析和配置向导 本文博客地址为:http://www.cnblogs.com/taosha/p/6716434.html ,转载请保留出处,多谢! 本地数据中心往云端迁移的的 ...

  8. jwt token Example - Python

    0 Pre Install Python3 Install PyCrypto Install PyJWT 1 token 由三部分组成 header, payload, sign 并用逗号连接各部分 ...

  9. Linux学习(一)

    Linux系统 1.组成部分 1.1内核负责的功能 1.1.1:系统内存管理 内存管理即管理物理内存和虚拟内存 (通过硬盘实现的,即swap space),长时间为被访问的内存块会被放到虚拟内存中,当 ...

  10. Linux - 进程间通信 - 信号量

    一.概念 简单来讲,信号量是一个用来描述临界资源的资源个数的计数器. 信号量的本质是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源(文件.外部设备等)来实现进程间通信, 他本身 ...