(转)使用CGLIB实现AOP功能与AOP概念解释
http://blog.csdn.net/yerenyuan_pku/article/details/52864395
使用CGLIB实现AOP功能
在Java里面,我们要产生某个对象的代理对象,这个对象必须要有一个特点,即这个对象必须实现一个接口,动态代理技术只能基于接口进行代理。有时候我们在做开发的时候,这个对象就没有实现接口,有人可能会说,它既然没有接口,那我就给它定义一个接口,这是不行的,因为有时候我们拿到一个对象,而这个对象是服务器产生给我们的,是服务器提供给我们的,又不是我们自己写的,动不动就给它定义一个接口,给它找个爸爸,哪那行呢?但我们现在要对它进行增强,这时用动态代理技术就不行了,动态代理技术只能是基于接口,那如果这个对象没有接口,又该怎么做呢?
那这时我们就需要使用另外一套API——CGLIB了,这套API,即使没有接口,它也可以帮我们产生这个对象的代理对象。它的内部是怎么去产生这个对象的代理对象的呢?——实际上产生的是这个对象的子类,也即我们把一个对象交给CGLIB,它返回出来的似乎是一个代理对象(但它不是要产生一个对象的代理对象),但其实这个代理对象就是这个对象的子类,利用子类的方式来创建代理对象。在Spring里面就是这样做的,Spring里面有一个AOP编程(即面向切面编程,说白了就是动态代理,我们经常会交给Spring一个对象,它就会返回代理对象给我们,它在返回代理对象的时候,首先会检查我们这个对象有没有实现一个接口,如果我们这个类有接口,它使用Java的动态代理技术来帮我们构建出代理对象;如果我们这个类没有实现接口,它会使用CGLIB这套API,采用创建子类的方式来创建代理对象)。
本文是建立在使用JDK中的Proxy技术实现AOP功能的案例的基础之上的,若要使用CGLIB这套API实现AOP功能,就要将其所需要的jar包导入项目中,所需的jar包有:
- asm-2.2.3.jar
- cglib-nodep-2.2.jar
首先将PersonServiceBean类的代码修改为:
public class PersonServiceBean {
private String user = null;
public String getUser() {
return user;
}
public PersonServiceBean() {}
public PersonServiceBean(String user) {
this.user = user;
}
public void save(String name) {
System.out.println("我是save()方法");
}
public void update(String name, Integer personid) {
System.out.println("我是update()方法");
}
public String getPersonName(Integer personid) {
System.out.println("我是getPersonName()方法");
return "xxx";
}
}
可发现PersonServiceBean类没实现一个接口,现在要想产生PersonServiceBean类的代理对象,这时就不能不使用CGLIB这套API了。
我们在it.cast.aop包下新建一个类——CGlibProxyFactory.java,与JDKProxyFactory类相似,都用于创建代理对象,其代码为:
public class CGlibProxyFactory implements MethodInterceptor {
private Object targetObject; // 代理的目标对象
public Object createProxyInstance(Object targetObject) {
this.targetObject = targetObject;
Enhancer enhancer = new Enhancer(); // 该类用于生成代理对象
enhancer.setSuperclass(this.targetObject.getClass()); // 设置目标类为代理对象的父类
enhancer.setCallback(this); // 设置回调用对象为本身
return enhancer.create();
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
PersonServiceBean bean = (PersonServiceBean)this.targetObject;
Object result = null;
if (bean.getUser() != null) { // 有权限
result = methodProxy.invoke(targetObject, args); // 把方法调用委派给目标对象
}
return result;
}
}
- 1
结论:CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。
接着就要修改AOPTest类的代码了,我们先将AOPTest类的代码改为:
public class AOPTest {
@Test
public void proxyTest() {
JDKProxyFactory factory = new JDKProxyFactory();
PersonService service = (PersonService) factory.createProxyInstance(new PersonServiceBean());
service.save("888");
}
@Test
public void proxyTest2() {
CGlibProxyFactory factory = new CGlibProxyFactory();
PersonServiceBean service = (PersonServiceBean) factory.createProxyInstance(new PersonServiceBean("xxx"));
service.save("999");
}
}
- 1
- 2
测试proxyTest2()方法,Eclipse控制台会打印:
若是将AOPTest类的代码改为:
public class AOPTest {
@Test
public void proxyTest() {
JDKProxyFactory factory = new JDKProxyFactory();
PersonService service = (PersonService) factory.createProxyInstance(new PersonServiceBean());
service.save("888");
}
@Test
public void proxyTest2() {
CGlibProxyFactory factory = new CGlibProxyFactory();
PersonServiceBean service = (PersonServiceBean) factory.createProxyInstance(new PersonServiceBean());
service.save("999");
}
}
- 1
再次测试proxyTest2()方法,Eclipse控制台什么都不会打印。
如要查看源码,可点击使用JDK中的Proxy技术实现AOP功能与使用CGLIB实现AOP功能进行下载。
AOP概念解释
AOP用在哪些方面:AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制,异常处理等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
AOP中的概念
Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是横切性关注点的抽象。
joinpoint(连接点):所谓连接点是指那些被拦截到的点(可以是方法、属性、或者类的初始化时机(可以是Action层、Service层、dao层))。在Spring中,这些点指的是方法,因为Spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器。
Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义,也即joinpoint的集合。
Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知。通知分为前置通知、后置通知、异常通知、最终通知、环绕通知。我们就以CGlibProxyFactory类的代码为例进行说明:
public class CGlibProxyFactory implements MethodInterceptor {
private Object targetObject; // 代理的目标对象
public Object createProxyInstance(Object targetObject) {
this.targetObject = targetObject;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.targetObject.getClass()); // 设置目标类为代理对象的父类
enhancer.setCallback(this);
return enhancer.create();
}
// 从另一种角度看: 整个方法可看作环绕通知
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
PersonServiceBean bean = (PersonServiceBean)this.targetObject;
Object result = null;
if (bean.getUser() != null) { // 有权限
// ...... advice() ----> 前置通知(所谓通知,就是我们拦截到业务方法之后所要干的事情)
try {
result = methodProxy.invoke(targetObject, args); // 把方法调用委派给目标对象
// ...... afteradvice() ----> 后置通知
} catch (RuntimeException e) {
// ...... exceptionadvice() ----> 异常通知
} finally {
// ...... finallyadvice() ----> 最终通知
}
}
return result;
}
}
Target(目标对象):代理的目标对象。
Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入。
Introduction(引入):在不修改类代码的前提下,Introduction可以在运行期为类(代理类)动态地添加一些方法或Field。
AOP带来的好处:降低模块的耦合度;使系统容易扩展;更好的代码复用性
(转)使用CGLIB实现AOP功能与AOP概念解释的更多相关文章
- Spring第九弹—使用CGLIIB实现AOP功能与AOP概念解释
JDK自从1.3版本开始,就引入了动态代理,并且经常被用来动态地创建代理,原理之前我已经讲过.JDK的动态代理用起来非常简单,但它有一个限制,就是使用动态代理的对象必须实现一个或多个接口.如果想代理没 ...
- 利用cglib包实现Spring中aop的<aop:advisor>功能
一:前言 还有<aop:before>/<aop:after>/<aop:around>的没有实现,不过根<aop:advisor>是差不多的,就是要额 ...
- Ioc 之 Unity的AOP功能
前面我们介绍了Unity的依赖注入功能,现在来介绍下Unity的AOP功能.AOP是面向切面编程,它能够使我们在不改变现有代码结构的情况下额外的为其添加一些功能. 我们还是使用配置文件来对类型进行注入 ...
- aop学习总结二------使用cglib动态代理简单实现aop功能
aop学习总结二------使用cglib动态代理简单实现aop功能 模拟业务需求: 1.拦截所有业务方法 2.判断用户是否有权限,有权限就允许用户执行业务方法,无权限不允许用户执行业务方法 (判断是 ...
- Spring AOP功能和目标
1.AOP的作用 在OOP中,正是这种分散在各处且与对象核心功能无关的代码(横切代码)的存在,使得模块复用难度增加.AOP则将封装好的对象剖开,找出其中对多个对象产生影响的公共行为,并将其封装为一个可 ...
- spring AOP 之一:spring AOP功能介绍
一.AOP简介 AOP:是一种面向切面的编程范式,是一种编程思想,旨在通过分离横切关注点,提高模块化,可以跨越对象关注点.Aop的典型应用即spring的事务机制,日志记录.利用AOP可以对业务逻辑的 ...
- SpringBoot中使用LoadTimeWeaving技术实现AOP功能
目录 1. 关于LoadTimeWeaving 1.1 LTW与不同的切面织入时机 1.2 JDK实现LTW的原理 1.3 如何在Spring中实现LTW 2. Springboot中使用LTW实现A ...
- Spring 框架的核心功能之AOP技术
1. AOP 的概述 AOP, Aspect Oriented Programming, 面向切面编程; 通过预编译方式和运行期动态代理实现程序功能的统一维护的技术; AOP 采取横向抽取机制,取代了 ...
- Spring框架的核心功能之AOP技术
技术分析之Spring框架的核心功能之AOP技术 AOP的概述 1. 什么是AOP的技术? * 在软件业,AOP为Aspect Oriented Programming的 ...
随机推荐
- javaScript的几个问题简答
1.javascript的typeof返回哪些数据类型 Object.number. function. boolean. underfind 2.例举3种强制类型转换和2种隐式类型转换? ...
- centos7 编译安装新版LNMP环境
centos7 编译安装新版LNMP环境 环境版本如下: 1.系统环境:Centos 7 x86_64 2.NGINX:nginx-1.11.3.tar.gz 3.数据库:mariadb-10.0.2 ...
- 获取服务器基本信息.sh
#获取linux服务器基本信息脚本 #!/bin/bash # #Name:system_info #Ver:1.0 #Author:lykyl # # #程序说明: #获取服务器基本信息脚本 # e ...
- 斯坦福CS231n—深度学习与计算机视觉----学习笔记 课时1
课时1 计算机视觉历史回顾与介绍上 CS231n:这一一门关于计算机视觉的课程,基于一种专用的模型架构,叫做神经网络(更细一点说,是卷积神经网络CNN).计算机视觉是人工智能领域中发展最为迅猛的一个分 ...
- lua-resty-r3 高性能 OpenResty 路由实现
大家下午好!首先做下自我介绍,我于 2014 年加入奇虎 360,后与温铭结识,当时他正在基于 OpenResty 做天擎服务端,用于提供 API 服务.2015 年我们一起写了< OpenRe ...
- P5163 WD与地图(整体二分+权值线段树)
传送门 细节要人命.jpg 这题思路太新奇了--首先不难发现可以倒着做变成加边,但是它还需要我们资瓷加边的同时维护强连通分量.显然加边之后暴力跑是不行的 然后有一个想法,对于一条边\((u,v)\), ...
- Java中JRE、JDK和JVM的区别
一.三者的基本概念: JRE(Java Development Kit):Java的运行环境: JDK(Java Runtime Enviroment):Java开发工具包: JVM(Java Vir ...
- 黑客攻防技术宝典web实战篇:攻击用户·其他技巧习题
猫宁!!! 参考链接:http://www.ituring.com.cn/book/885 随书答案. 1. 已知一项应用程序功能将一个查询字符串参数的内容插入到某个 HTTP 重定向的 Locati ...
- 第五篇 .NET高级技术之CTS、CLS、CLR
CTS.CLS.CLR 1. .Net平台下不只有C#语言,还有VB.Net.F#等语言.IL是程序最终编译的可以执行的二进制代码(托管代码),不同的语言最终都编译成标准的IL(中间语言,MSIL): ...
- 如何用Zookeeper来实现分布式锁?
什么是Zookeeper临时顺序节点? 例如 : / 动物 植物 猫 仓鼠 荷花 松树 Zookeeper的数据存储结构就像一棵树,这棵树由节点组成,这种节点叫做Zonde.# Znode分为四种类型 ...