jdk动态代理与cglib代理、spring aop代理实现原理
原创声明:本博客来源与本人另一博客【http://blog.csdn.net/liaohaojian/article/details/63683317】原创作品,绝非他处摘取
代理(proxy)的定义:为某对象提供代理服务,拥有操作代理对象的功能,在某些情况下,当客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
动态代理实现主要有2种形式,主要分为:
1.jdk动态代理:
1)原理:是根据类加载器和接口创建代理类(此代理类是接口的实现类,所以必须使用接口 面向接口生成代理,位于java.lang.reflect包下)
2)实现方式:
1. 通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(…);
2. 通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…});
3. 通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4. 通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
2~4步骤可合并
package proxy.jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.junit.Test;
public class JDKProxy{
//写法1
private Object targetObject;//代理目标
public Object CustomerProxy(Object obj) {
targetObject = obj;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(),new targetHandler());
}
class targetHandler implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开启事务...");
Object returnValue = method.invoke(targetObject, args);//回调被代理目标的方法userDaoImpl.add();
System.out.println("提交事务");
return returnValue;
}
}
public static void main(String[] args) {
JDKProxy jdkProxy = new JDKProxy();
Customer userDao = (Customer)jdkProxy.CustomerProxy(new CustomerImpl());
userDao.shopping();
}
//写法2
@Test
public void test1(){
Customer customer = new CustomerImpl();
Customer cus = (Customer) Proxy.newProxyInstance(customer.getClass().getClassLoader(), customer.getClass().getInterfaces(),new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
return method.invoke(proxy, args);
}
});
cus.shopping();
}
}
3)不足点:jdk动态代理,必须是面向接口,目标业务类必须实现接口
2.CGLIB代理
1.原理:利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
2.实现方法:
package proxy.cglib;
import java.lang.reflect.Method;
import org.junit.Test;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import proxy.model.Customer;
public class CGLIBProxy {
//写法1
private Object targetObject;
private Object createProxy(Object obj){
targetObject = obj;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetObject.getClass());//设置代理对象,父类,说明是继承,所有代理对象不能为final
enhancer.setCallback(new MyHandler());
return enhancer.create();//创建代理
}
class MyHandler implements MethodInterceptor{
@Override
public Object intercept(Object arg0, Method method, Object[] args,
MethodProxy arg3) throws Throwable {
System.out.println("开启事务..");
Object returnValue = method.invoke(targetObject, args);
System.out.println("提交事务....");
return returnValue;
}
}
@Test
public void test1() {
CGLIBProxy cglibProxy = new CGLIBProxy();
Customer customer = (Customer)cglibProxy.createProxy(new Customer());
customer.eat();
}
//写法2
@Test
public void test2(){
Customer customer = new Customer();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(customer.getClass());
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy arg3) throws Throwable {
if(method.getName().equals("eat")){
System.out.println("customer的eat方法被拦截了。。。。");
Object invoke = method.invoke(proxy, args);
System.out.println("真实方法拦截之后。。。。");
return invoke;
}
// 不拦截
return method.invoke(proxy, args);
}
});
Customer cus = (Customer) enhancer.create();
cus.eat();
}
}
3.注意点:被代理目标不是是final修饰的类(final修饰类不能被继承)
spring aop代理原理
1.注意点:
- 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
- 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
- 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
2.强制把jdk代理转换成cglib代理
- 添加CGLIB库,SPRING_HOME/cglib/*.jar
- 在spring配置文件中加入
传统AOP可以实现自动代理,不需要专门指定代理,可以在类生成的时候自动代理,有两种方式实现自动代理,基于Bean名称的自动代理BeanNameAutoProxyCreator和基于切面信息的自动代理DefaultAdvisorAutoProxyCreator
spring mvc 使用DefaultAdvisorAutoProxyCreator实现自动代理 配置
<!--定义一个表示声明使用自动代理的类 -->
<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<!-- 定义代理类 -->
<bean id="exceptionHandler" class="com.kaizhi.platform.util.ExceptionHandler"/>
<!-- 定义支持正则表达式的通知 -->
<bean id="exceptionHandlerAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref bean="exceptionHandler"/>
</property>
<property name="patterns">
<value>.save*.*</value>//正则匹配需要拦截的方法
</property>
</bean>
spring mvc 使用BeanNameAutoProxyCreator自动代理配
<!-- 基于BeanNameAutoProxyCreator,Bean名称的自动代理 -->
<!-- 定义代理类 -->
<bean id="exceptionHandler" class="com.kaizhi.platform.util.ExceptionHandler"/>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!-- 拦截的业务bean -->
<property name="beanNames" value="*adminFinanceService"/>
<!-- 拦截的通知 -->
<property name="interceptorNames" value="exceptionHandler"/>
</bean>
参考:http://blog.csdn.net/zx13525079024/article/details/51913141
jdk动态代理与cglib代理、spring aop代理实现原理的更多相关文章
- Spring AOP 的实现 原理
反射实现 AOP 动态代理模式实例说明(Spring AOP 的实现 原理) 比如说,我们现在要开发的一个应用里面有很多的业务方法,但是,我们现在要对这个方法的执行做全面监控,或部分监控.也许我们 ...
- jdk动态代理与cglib代理、spring aop代理实现原理解析
原创声明:本博客来源为本人原创作品,绝非他处摘取,转摘请联系博主 代理(proxy)的定义:为某对象提供代理服务,拥有操作代理对象的功能,在某些情况下,当客户不想或者不能直接引用另一个对象,而代理对象 ...
- 何为代理?jdk动态代理与cglib代理、spring Aop代理原理浅析
原创声明:本博客来源为本人原创作品,绝非他处摘取,转摘请联系博主 代理(proxy)的定义:为某对象提供代理服务,拥有操作代理对象的功能,在某些情况下,当客户不想或者不能直接引用另一个对象,而代理对象 ...
- jdk动态代理与cglib代理、spring Aop代理原理-代理使用浅析
原创声明:本博客来源为本人原创作品,绝非他处摘取,转摘请联系博主 代理(proxy)的定义:为某对象提供代理服务,拥有操作代理对象的功能,在某些情况下,当客户不想或者不能直接引用另一个对象,而代理对象 ...
- 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。
基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...
- Spring -- <tx:annotation-driven>注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别。
借鉴:http://jinnianshilongnian.iteye.com/blog/1508018 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional ...
- Spring <tx:annotation-driven>注解 JDK动态代理和CGLIB动态代理 区别。
基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...
- JDK动态代理和CGLIB代理的区别
一.原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件 ...
- java中代理,静态代理,动态代理以及spring aop代理方式,实现原理统一汇总
若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. ...
随机推荐
- 关于hive ,eclipse老是提示加载不到驱动
忙活了好长时间,很纳闷为什么加载不上驱动,驱动包.hive的依赖包.hadoop的依赖包也引入了,各种百度最后: hadoop-2.2.0/share/hadoop/common/hadoop-com ...
- CSS3形变——transform与transform-origin画时钟
css3属性transform和transform-origin"画"时钟 效果图 前言 八哥:哈喽,大家好!好攻城狮就是我就是你们的小八,欢迎收听你的月亮...哦不,是很高兴与你 ...
- [.net 面向对象程序设计深入](13)实战设计模式——设计模式使用场景及原则
[.net 面向对象程序设计深入](13)实战设计模式——设计模式使用场景及原则 1,什么是设计模式? 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计 ...
- Archlinux 的U盘自动装载(三)udevil
U盘的自动装载方法,目前我已经使用过以下几种方法: udev 规则 基于 udev 规则的 Shell script udisks 以及 udisks2 结果,总是存在这样那样的小问题.例如,文件名乱 ...
- arcgisserver成功发布服务后,浏览服务,无地图显示
软件:ArcMap10.2,ArcgisCatalog10.2 方法:ArcMap10.2添加数据库连接,成功登陆数据库后,拖拽目标图层至Map窗口,对各个图层进行符号化设置 ArcCatalog中找 ...
- 在Pypi上发布自己的Python包
使用Python编程的都知道,Python的包安装非常的方便,一般都是可以pip来安装搞定: sudo pip install <package name> pip的安装请移步:https ...
- JAVA基础知识(1)
1.JAVA的三大体系:JME(微缩版),JSE(标准版),JEE(企业版): 2.JAVA的三大核心机制:JAVA虚拟机,垃圾回收机制,代码安全性检测 3.java开发集JDK 4.java编译器j ...
- JQ万能轮播图
lunbotu.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...
- 解决ubuntu更新中断后报错问题
今天在更新ubuntu的时候,更新了一半被我强制关闭了,就报错了 当再使用sudo apt-get update命令时出现了dpkg was interrupted,you must manually ...
- Repaints and Reflows 重绘和重排版
当浏览器下载完所有页面HTML标记,JavaScript,CSS,图片之后,它解析文件并创建两个内部数据 一棵DOM树 表示页面结构 Normal 0 7.8 磅 0 2 false false fa ...