[转]JAVA的动态代理机制及Spring的实现方式
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的实现方式的更多相关文章
- Spring学习(二)—— java的动态代理机制
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
- java的动态代理机制详解
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
- Java的动态代理机制详解(转)
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
- (转)java的动态代理机制详解
原文出自:http://www.cnblogs.com/xiaoluo501395377/p/3383130.html 在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一 ...
- [转载] java的动态代理机制详解
转载自http://www.cnblogs.com/xiaoluo501395377/p/3383130.html 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代 ...
- 【转】java的动态代理机制详解
java的动态代理机制详解 在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们 ...
- java的动态代理机制
前几天看到java的动态代理机制,不知道是啥玩意,然后看了看.死活不知道 invoke(Object proxy, Method m, Object[] args)种的proxy是个什么东西,放在这里 ...
- java的动态代理机制详解-----https://www.cnblogs.com/xiaoluo501395377/p/3383130.html
java的动态代理机制详解-----https://www.cnblogs.com/xiaoluo501395377/p/3383130.html
- Java 动态代理机制详解
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
随机推荐
- java 基础知识七 装箱和拆箱
java 基础知识七 装箱和拆箱 数据类型可分为两大种,基本数据类型(值类型)和类类型(引用数据类型) 装箱:把基本类型用他们相对应的引用类型包装起来,使他们可以具有对象的特质 基本数据类型 ...
- CSS3实现一束光划过图片、和文字特效
在打折图标里面 实现一道白光划过的动画效果 css: <!DOCTYPE html><html><head><meta charset="utf-8 ...
- Spring MVC__自定义日期类型转换器
WEB层采用Spring MVC框架,将查询到的数据传递给APP端或客户端,这没啥,但是坑的是实体类中有日期类型的属性,但是你必须提前格式化好之后返回给它们.说真的,以前真没这样做过,之前都是一口气查 ...
- Rookey.Frame v1.0极速开发平台稳定版发布
Rookey.Frame v1.0经过一年时间的修改及沉淀,稳定版终于问世了,此版本经过上线系统验证,各个功能点都经过终端用户验证并持续优化,主要优化以下几个方面: 1.性能较原来提升3倍之多 2.修 ...
- 第十章 MyBatis入门
第十章 MyBatis入门10.1 MyBatis入门 优点:简单且功能强大.能够完全控制SQL语句.容易维护和修改 缺点:移植性不好 使用步骤: 1.下载 ...
- SQL生成一年每一天的时间列表的几种方法
工作好几年了,一直没有写博客,准备捡起来... 以下脚本适用环境:SQL SERVER (starting with 2012) 1.构建序列: /*1-1:利用交叉连接,推荐下列这种写法 ...
- StringHelper--封转自己的字符串工具类
我们每次开发项目,都会有很多的关于字符串的处理,字符串的处理太常见了,无法避免,那么这时如果可以把常用的字符串处理封装成类,在以后的开发中应该会减少一些工作量,下面代码对一些常用的字符串处理进行了封装 ...
- python字符串实战
haproxy配置文件 思路:读一行,写一行 global log 127.0.0.1 local2 daemon maxconn 256 log 127.0.0.1 local2 info defa ...
- 好久没发贴了,最近捣鼓了个基于node的图片压缩小网站解析。
看了下,距离上次发帖都是去年10月份的事,忙于工作的我很少跑博客园里面来玩了. 做这个小网站的初衷是 https://tinypng.com/ 这个网站有时候访问很慢,然后自己去研究了下图片压缩. 网 ...
- 转Fiddler 构造http请求
今天使用Fiddler构造一个POST请求,server端的PHP脚本的 $_POST数组中怎么也获取不到值,后来偶然发现是因为缺少了一个http头:Content-Type: application ...