文档章节

spring aop-代理篇,java Proxy代理&cglib代理

haoran_10
 haoran_10
发布于 2016/07/15 16:37
字数 1052
阅读 67
收藏 0
点赞 0
评论 0

一、java原生代理

1、代理概念介绍

为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理 对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行 完请求后的后续处理。

2、代理分类

java代理分为两类,静态代理和动态代理。

静态代理通过代码的编写,生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。

动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。

3、动态代理示例

使用java.lang.reflect.Proxy进行创建

3.1 接口部分

使用Proxy创建代理,必须预先定义接口

package wang.conge.javasedemo.core.proxy; public interface HelloService { public String sayHello(String name); } 

3.2 业务实现部分

package wang.conge.javasedemo.core.proxy;

public class HelloServiceImpl implements HelloService {

    @Override
    public String sayHello(String name) {
        return "hello:" + name;
    }

}

3.3 代理业务部分

package wang.conge.javasedemo.core.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class HelloInvocationHandler implements InvocationHandler{
    private Object delegate; 
    
    public HelloInvocationHandler(Object delegate){
        this.delegate = delegate;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("invoke");
        return method.invoke(this.delegate, args);
    }

}

3.4 测试代码

package wang.conge.javasedemo.core.proxy;

import java.lang.reflect.Proxy;

public class JavaProxyTest {
    public static void main(String[] args) {
        HelloInvocationHandler invocationHandler = new HelloInvocationHandler(new HelloServiceImpl());

        HelloService helloService = (HelloService) Proxy.newProxyInstance(HelloService.class.getClassLoader(),
                new Class[] { HelloService.class }, invocationHandler);

        System.out.println(helloService.sayHello("conge"));
    }
}

运行结果

invokehello:conge

3.5 Proxy代理总结

用法总结:

主要使用java.lang.reflect.Proxy 进行创建代理类
主要方法:public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h);

第一个参数是ClassLoader,也即是加载所要代理类的相应的ClassLoader
第二个参数是interfaces,即是所要代理类的接口
第三个参数是代理业务部分,需要实现InvocationHandler接口
                                          

优缺点总结:

优点:
1、可以替代java静态代理,集中式处理

缺点:
1、所代理的类,必须预先定义接口,不能直接没有定义接口的类
2、所代理的接口也必须是public类型,如果是package ,必须在访问包的顶层目录

二、Cglib代理

因为Proxy不能代理没有定义接口的类,缺陷比较大。但还有另外一个方案可以解决这个问题。cglib。

1.cglib介绍

cglib简述
           Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用CGLIB即使代理类没有实现任何接口也可以实现动态代理功能。CGLIB具有简单易用,它的运行速度要远远快于JDK的Proxy动态代理:
使用CGLIB需要导入以下两个jar文件:
    $1:    asm.jar – CGLIB的底层实现
    $2:   cglib.jar – CGLIB的核心jar包。
CGLIB的核心类:
    net.sf.cglib.proxy.Enhancer – 主要的增强类
    net.sf.cglib.proxy.MethodInterceptor – 主要的方法拦截类,它是Callback接口的子接口,需要用户实现
    net.sf.cglib.proxy.MethodProxy – JDK的Java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用,如使用:
    Object o = methodProxy.invokeSuper(proxy, args);//虽然第一个参数是被代理对象,也不会出现死循环的问题。

2.使用cglib进行代理

2.1 所依赖cglib

<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.2</version></dependency>

2.2 业务服务

还是使用java原生代理的HelloServiceImpl , see 原生代理3.2

2.3 代理业务部分

package wang.conge.javasedemo.core.cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class HelloCglibHandler implements MethodInterceptor {
    private Object delegate; 
    
    public HelloCglibHandler(Object delegate){
        this.delegate = delegate;
    }
    
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("intercept");
        return method.invoke(delegate, args);
    }

}

2.4 测试代码

package wang.conge.javasedemo.core.cglib;

import net.sf.cglib.proxy.Enhancer;
import wang.conge.javasedemo.core.proxy.HelloServiceImpl;

public class EnhancerTest {
    public static void main(String[] args) {
        HelloCglibHandler cglibHandler = new HelloCglibHandler(new     HelloServiceImpl());

        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(HelloServiceImpl.class);
        enhancer.setCallback(cglibHandler);
        
        HelloServiceImpl helloService = (HelloServiceImpl) enhancer.create();
        
        System.out.println(helloService.sayHello("conge"));
    }
}

运行结果:

intercepthello:conge

2.5 cglib代理总结

 

主要使用Enhancer进行创建代理类,可以直接对类进行代理,运行速度也比原生代理要快。

© 著作权归作者所有

共有 人打赏支持
haoran_10
粉丝 25
博文 88
码字总数 80846
作品 0
杭州
程序员
JDK动态代理与Cglib动态代理(转载)

spring容器通过动态代理再结合java反射思想可以使得方法调用更加简洁 一、动态代理概述: 与静态代理对照(关于静态代理的介绍 可以阅读上一篇:JAVA设计模式之 代理模式【Proxy Pattern】(...

思悟修
2015/08/14
0
0
CGLIB子类代理和JDK动态代理示例和比较

Cglib代理,也叫做子类代理。在内存中构建一个子类对象从而实现对目标对象功能的扩展。 比较: JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现...

AI9o後
2017/11/06
0
0
cglib代理和java自带代理的区别

一 动态代理主要有java自带的代理和cglib方式实现的代理 首先讲下java自带的代理 ------------------然后是cglib自带的代理------------------------- 测试类: java动态代理是利用反射机制生...

sen_ye
07/15
0
0
Spring的事务管理难点剖析(6):特殊方法成漏网之鱼

由于Spring事务管理是基于接口代理或动态字节码技术,通过AOP实施事务增强的。虽然Spring还支持AspectJ LTW在类加载期实施增强,但这种方法很少使用,所以我们不予关注。 对于基于接口动态代...

icheer
2012/07/17
0
0
Spring AOP 实现原理与 CGLIB 应用

AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等。AOP 实现的关键就在于 AOP 框架...

只想一个人静一静
2014/02/27
0
0
Spring AOP 实现原理与 CGLIB 应用

AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等。AOP 实现的关键就在于 AOP 框架...

ihaolin
2014/03/31
0
0
Java反射与 JDK代理调用

最近因为项目需要温习Spring的时候,看到有一章节讲的是JDK代理调用,所以就结合公司的Invoke代理调用再一次看了一遍代理这一块。 一、反射 通常java中都是由java类编译成class文件,即先有类...

南栀安
2017/10/30
0
0
Spring之使用注解配置Spring AOP

Spring框架通过注解配置AOP是基于AspectJ实现的。 Spring框架只是直接使用了AspectJ的注解,但并没有使用AspectJ的编译器或织入器,仍然是在运行时动态生成AOP代理。 aspectj使用的是静态代理...

Java攻城玩家
05/31
0
0
1000行代码读懂Spring(二)- 在Spring中实现AOP

关于AOP AOP是Spring核心功能之一。今天就用tiny-spring来实现一个AOP。具体功能会包括: 读取AspectJ格式的Pointcut描述。 使用JDK动态代理以及CGLib两种方式进行AOP织入。 AOP分为配置(Po...

黄亿华
2014/01/20
0
3
说说 Spring AOP 的底层实现技术(JDK 与 CGLib 动态代理)

Spring AOP 使用了两种代理机制: 基于 JDK 的动态代理(接口代理)。 基于 CGLib 的动态代理(类代理)。 1 订单服务实例 假设有这样的一个订单服务,它提供新增订单的方法,我们需要对这个...

deniro
06/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Laravel5.5 MySQL配置、读写分离及操作

Laravel 让连接不同数据库以及对数据库进行增删改查操作: 参考:http://laravelacademy.org/post/854.html 配置读写分离 应用的数据库配置位于 config/database.php(但是数据库用户及密码等...

MichaelShu
5分钟前
0
0
TraitsUI与Mayavi实例

一:创建一个简单的TraitsUI与Mayavi实例 # -*- coding: utf-8 -*-from numpy import sqrt,sin,mgridfrom traits.api import HasTraits,Instancefrom traitsui.api import View,Item......

wangxuwei
10分钟前
0
0
Linux 查看用户

存储帐号的文件:/etc/passwd 存储密码的文件:/etc/shadow 查看当前系统所有用户 grep bash /etc/passwd root修改普通用户的密码 sudo passwd user_name 然后连续两次输入新的用户密码即可...

yeahlife
12分钟前
0
0
Webpack使用nodemon实时打包编译

业务场景: 1.编写一个npm组件包并且link到了项目文件中 2.需要不断的修改并run build编译npm包并且在项目run dev 查看效果 3.问题: 每次改完npm包都要手动run build编译十分的麻烦且低效,可不...

JamesView
23分钟前
0
0
电脑炸了,浪费我好几天时间,还是简要记下来吧

我的小本本一直在兢兢业业的干活,然而前几天说炸就炸了...... 爆炸现场: 软件: windows10 pro + EIS11+ 360卫士 BIOS:N1DET98W 2.24 硬件: Xeon E3 1505-V5 nv-M3000M thinkpadP70:20E...

Oh_really
27分钟前
0
0
Git之branch和checkout

1.branch是查看、创建、删除分支 #>git branch --helpNAME git-branch - List, create, or delete branchesSYNOPSIS git branch [--color[=<when>] | --no-color] [......

汉斯-冯-拉特
29分钟前
0
0
Mybatis拦截器之数据权限过滤与分页集成

需求场景 最近项目有个数据权限的业务需求,要求大致为每个单位只能查看本级单位及下属单位的数据,例如:一个集团军下属十二个旅,那么军级用户可以看到所有数据,而每个旅则只能看到本旅部...

佛系程序猿灬
38分钟前
9
0
SpringCloud 微服务 (十六) 服务追踪 Zipkin

问题 在服务中,有一个接口,该A接口中又调用了其他服务的B、C、D接口,出现一个请求耗时大的问题,这时候并不知道该B、C、D接口中哪个接口造成的耗时量,然后比如确定C服务接口出现的耗时量大,但...

___大侠
今天
0
0
Java面试基础篇——第八篇:抽象类与接口的区别

1.抽象类 抽象类:如果一个类中包含有抽象方法,或这个类使用abstract关键字修饰,则称这个类是抽象类。 抽象方法是什么呢?抽象方法就是指用abstract关键字修饰的方法。 需要注意的是:抽象...

developlee的潇洒人生
今天
2
0
jsoup 相关资料

1.jsoup 2.Jsoup概述 3.jsoup入门 4.jsoup Java HTML Parser 1.11.3 API

IT追寻者
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部