2017-11-10 16:17:12

AOP中有两种代理方式,分别是JDK的动态代理CGLib的动态代理

  • JDK的动态代理

Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

目标对象必须要实现某种接口。

动态代理类(以下简称为代理类)是一个实现在创建类时在运行时指定的接口列表的类,该类具有下面描述的行为。 代理接口 是代理类实现的一个接口。 代理实例 是代理类的一个实例。 每个代理实例都有一个关联的调用处理程序 对象,它可以实现接口 InvocationHandler。通过其中一个代理接口的代理实例上的方法调用将被指派到实例的调用处理程序的 Invoke 方法,并传递代理实例、识别调用方法的 java.lang.reflect.Method 对象以及包含参数的 Object 类型的数组。调用处理程序以适当的方式处理编码的方法调用,并且它返回的结果将作为代理实例上方法调用的结果返回。

* 常用方法

// 接口
public interface Person {
public void add();
public void delete();
} // 实现类
public class Student implements Person {
@Override
public void add() {
System.out.println("添加操作...");
} @Override
public void delete() {
System.out.println("删除操作...");
}
} // 测试
public class Demo {
public static void main(String[] args) {
Student s= new Student();
// JDK Proxy操作
Person proxy = (Person) Proxy.newProxyInstance(s.getClass().getClassLoader(),
s.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进行身份校验...");
Object res = method.invoke(s, args);
return res;
}
});
proxy.add();
}
}
  • CGLib的动态代理
CGLIB(Code Generation Library)是一个开源项目。
是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Hibernate支持它来实现PO(Persistent Object 持久化对象)字节码的动态生成。
最新版本Spring已经将CGLib开发类引入spring-core-3.2.0.RELEASE.jar,所以不用导包。
CGLIB不需要接口也是可以生成代理的。
本质是通过继承的方式进行增强。
1、CGLib的原理
CGLIB动态代理的原理就是用Enhancer生成一个原有类的子类,并且设置好callback到proxy, 则原有类的每个方法调用都会转为调用实现了MethodInterceptor接口的proxy的intercept() 函数,如图

在intercept()函数里,除执行代理类的原因方法,在原有方法前后加入其他需要实现的过程,改变原有方法的参数值,即可以实现对原有类的代理了。这似于AOP中的around advice。

2、使用MethodInterceptor接口实现方法回调

当对代理中所有方法的调用时,都会转向MethodInterceptor类型的拦截(intercept)方法,在拦截方法中再调用底层对象相应的方法。下面我们举个例子,假设你想对目标对象的所有方法调用进行权限的检查,如果没有经过授权,就抛出一个运行时的异常。

net.sf.cglib.proxy.MethodInterceptor接口是最通用的回调(callback)类型,它经常被基于代理的AOP用 来实现拦截(intercept)方法的调用。

MethodInterceptor接口只定义了一个方法:

public Object intercept(Object object, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable;

参数Object object是被代理对象,不会出现死循环的问题。

参数java.lang.reflect.Method method是java.lang.reflect.Method类型的被拦截方法。

参数Object[] args是被被拦截方法的参数。

参数MethodProxy proxy是CGLIB提供的MethodProxy 类型的被拦截方法。

注意:

1、若原方法的参数存在基本类型,则对于第三个参数Object[] args会被转化成类的类型。如原方法的存在一个参数为int,则在intercept方法中,对应的会存在一个Integer类型的参数。

2、若原方法为final方法,则MethodInterceptor接口无法拦截该方法。

// 目标类
public class Student implements Person {
@Override
public void add() {
System.out.println("添加操作...");
} @Override
public void delete() {
System.out.println("删除操作...");
}
} // 实现MethodInterceptor接口的实现类
public class CGLibProxy implements MethodInterceptor {
// 首先得获得该对象
Student s; // 通过构造函数来初始化
CGLibProxy(Student s){
this.s = s;
} // 创建代理
public Student newProxy(){
// 创建CGLib的核心类
Enhancer en = new Enhancer();
// 由于CGLib是通过继承方式实现的,所以需要进行父类的设置
en.setSuperclass(s.getClass());
// 设置回调函数,因为当前类实现了Callback接口的子接口MethodInterceptor
// 所以在回调函数里传的参数是this,并且在每次调用目标对象的方法的时候,其实
// 是在调用intercept方法
en.setCallback(this);
// 返回代理对象
return (Student) en.create();
} @Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("进行权限校验...");
Object res = methodProxy.invokeSuper(o, objects);
return res;
}
} // 测试
public class Demo {
public static void main(String[] args) {
Student s= new Student(); // CGLib的动态代理
CGLibProxy cg = new CGLibProxy(s);
Student p = cg.newProxy();
p.add();
}
}
  • 结论:Spring框架,如果类实现了接口,就使用JDK的动态代理生成代理对象,如果这个类没有实现任何接口,使用CGLIB生成代理对象

Java Spring-AOP中的动态代理的更多相关文章

  1. Spring AOP中的动态代理

    0  前言 1  动态代理 1.1 JDK动态代理 1.2 CGLIB动态代理 1.2.1 CGLIB的代理用法 1.2.2 CGLIB的过滤功能 2  Spring AOP中的动态代理机制 2.1  ...

  2. 转:Spring AOP中的动态代理

    原文链接:Spring AOP中的动态代理 0  前言 1  动态代理 1.1 JDK动态代理 1.2 CGLIB动态代理 1.2.1 CGLIB的代理用法 1.2.2 CGLIB的过滤功能 2  S ...

  3. Spring Boot实践——Spring AOP实现之动态代理

    Spring AOP 介绍 AOP的介绍可以查看 Spring Boot实践——AOP实现 与AspectJ的静态代理不同,Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改 ...

  4. spring---aop(4)---Spring AOP的CGLIB动态代理

    写在前面 前面介绍了Spring AOP的JDK动态代理的过程,这一篇文章就要介绍下Spring AOP的Cglib代理过程. CGLib全称为Code Generation Library,是一个强 ...

  5. Spring AOP实现原理-动态代理

    目录 代理模式 静态代理 动态代理 代理模式 我们知道,Spring AOP的主要作用就是不通过修改源代码的方式.将非核心功能代码织入来实现对方法的增强.那么Spring AOP的底层如何实现对方法的 ...

  6. Spring AOP系列(二) — 动态代理引言

    接上一篇Spring AOP系列(一)- 代理模式,本篇来聊聊动态代理. 动态代理与静态代理的区别 要想了解动态代理与静态代理的区别,需要有两个前置知识点:java程序是如何执行的以及类加载机制. j ...

  7. Spring AOP关于cglib动态代理

    一: Spring AOP的默认代理方式是jdk动态代理,还有另外一种代理方式是cglib代理,简单说前者基于接口,后者基于继承,基本思路是将被代理对象的类作为父类,然后创建子类来进行方法的调用,调用 ...

  8. spring---aop(2)---Spring AOP的JDK动态代理

    写在前面 spring 事务是springAOP 的一个实现.我们以分析spring的事务,来分析spring的AOP实现. 基本知识 如果目标方法被spring的事务声明,则执行该目标方法的对象就会 ...

  9. Spring AOP系列(三) — 动态代理之JDK动态代理

    JDK动态代理 JDK动态代理核心是两个类:InvocationHandler和Proxy 举个栗子 为便于理解,首先看一个例子: 希望实现这样一个功能:使用UserService时,只需关注自己的核 ...

  10. Spring AOP源码分析--代理方式的选择

    能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! 年前写了一个面试突击系列的文章,目前只有redis相关的.在这个系列里,我整理了一些面试题与大家 ...

随机推荐

  1. 01.MyBatis入门

        MyBatis入参考文档:http://mybatis.org/mybatis-3/zh/  1.使用MyBatis前的准备 1.增加Maven依赖 <dependency> &l ...

  2. oracle权限赋予

    上节讲的创建的software用户能否访问其他用户的表呢 1,创建software用户,密码设置为system create user software identified by system 2, ...

  3. 南京网络赛J-Sum【数论】

    A square-free integer is an integer which is indivisible by any square number except 11. For example ...

  4. 徐州网络赛B-BE,GE or NE【记忆化搜索】【博弈论】

    In a world where ordinary people cannot reach, a boy named "Koutarou" and a girl named &qu ...

  5. The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path(Myeclipse添加Server Library)

    网上找练习的项目导入到myeclipse项目发现每个JSP 出现错误The superclass "javax.servlet.http.HttpServlet" was not ...

  6. 由SOAP说开去 - - 谈谈WebServices、RMI、RPC、SOA、REST、XML、JSON

    引子: 关于SOAP其实我一直模模糊糊不太理解,这种模模糊糊的感觉表述起来是这样: 在使用web服务时(功能接口),本来我就可以通过安卓中固有的http类(使用http协议),来发送http请求,并且 ...

  7. 日志汇总:logging、logger

    目录 1.日志输出到文件 2.日志输出到屏幕 3.设置输出等级 4.设置多个日志输出对象 5.日志的配置 6.记录异常 7.设置日志输出样式 1.日志输出到文件basicConfig()提供了非常便捷 ...

  8. 【调研与分析】标杆学习、知识管理和竞争情报的关系——From Team

    注: 1)红色实线箭头表示可以直接使用:例如竞争情报业务输出产品之一的标杆文档可以直接作为公司标杆学习中外部标杆的资料: 2)蓝色虚线箭头表示转化后使用或者间接利用的关系:例如专题调研可以帮助建立内部 ...

  9. mysql 整数类型 数值类型 tinyint

    1.整数类型 整数类型:TINYINT SMALLINT MEDIUMINT INT BIGINT 作用:存储年龄,等级,id,各种号码等 ============================== ...

  10. Windows上的巧克力味Chocolatey详解

    Chocolatey是什么?很简单,Chocolatey就是Windows系统的yum或apt-get. 一.Chocolatey介绍 Chocolatey是一款专为Windows系统开发的.基于Nu ...