博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
09Spring_AOP介绍和java本身的动态代理以及cglib代理
阅读量:5843 次
发布时间:2019-06-18

本文共 3678 字,大约阅读时间需要 12 分钟。

Aspect Oriented Programming 面向切面编程

1.

业界 AOP 实际上 OOP (面向对象编程 ) 延伸 ----  OOP编程语言、 AOP设计思想,下面给出一张AOP的设计思想图。

看左边的的图,UserDao里面定义了两个方法,save方法还有delete方法,我想在执行这两个方法的时候都能打印出日志。java的方法是采用继承,我们写一个抽象的类(Basedao),里面定义了public void writeLog()这个打印日志的方法。然后让UserDao这个类继承BaseDao这样可以实现我要的功能,但是,这么做的话,有一个问题,这样做就破坏了类的结构,因为一个类继承了另外一个类的话会相当于多了一些父类的方法,这样做不好,是属于侵入式复用。所以提出了动态代理,AOp的概念。横向抽取代码复用,基于代理技术,在不修改原有对象代码情况下,对原有对象方法功能进行增强! ---------- AOP 思想

 

 

2.

接下来介绍一下Spring框架是怎么实现的AOp的

 

3.

接下来介绍AOP的相关术语:

4.Aop的底层实现:

Spring AOP 代理实现有两种: JDK动态代理 和 Cglib框架动态代理

JDK API 内置 ---- 通过 Proxy类,为目标对象创建代理 (必须面向接口代理)

 

JDK API 内置 ---- 通过 Proxy类,为目标对象创建代理 (必须面向接口代理 )public class JdkProxyFactory implements InvocationHandler {    // 被代理对象    private Object target;    // 在构造方法对象时,传入被代理对象    public JdkProxyFactory(Object target) {        this.target = target;    }    // 创建代理    public Object createProxy() {        // 三个参数: 类加载器、 实现接口、 invocationhandler        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("记录日志!!!!!!");        // 调用目标真实方法        // target 被代理对象, args 方法参数 , method 被调用的方法        return method.invoke(target, args);    }}

 

 

 

因为采用java的动态代理的话必须要求有接口所以为了解决这个问题,提出了Cglib 动态代理

 

CGLIB(Code Generation Library)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。

 

 

 

Cglib 不但可以对接口进行代理,也可以对目标类对象,实现代理 (解决了 Jdk 只能对接口代理问题 )

 

下载网址:  

 

-------  在spring3.2版本 core包中内置cglib  

 

 

所以我们可以直接使用,而不需要特意去导入Cglib的包, 我们编写一个Cglib动态代理的程序:

结构图如下:

CglibproxyFactory.java是代理类。CglibProcyTest是Junit的测试类,ProductDAo是被代理的对象。CglibproxyFactory这个代理类仿照前面的java原生代理(JdkProxyFactory )写。

CglibProxyFacory的代码如下:

package b_cglib;import java.lang.reflect.Method;import org.springframework.cglib.proxy.Enhancer;import org.springframework.cglib.proxy.MethodInterceptor;import org.springframework.cglib.proxy.MethodProxy;/* * Create by 沈晓权 * Create on 2016年7月26日下午10:32:55 */public class CglibProxyFactory  implements MethodInterceptor{private Object target;/** *  */public CglibProxyFactory( Object object) {this.target=object;}//创建代理的方法public Object createProxy(){
//1.创建Enhancer对象 Enhancer enhancer=new Enhancer(); //2.cglib创建代理,对目标对象,创建子类(cglib实现代理是通过子类这种形式创建的) enhancer.setSuperclass(target.getClass()); //3.这一步相当于之前的JdkProxyFactory中的Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); 最后那个this传入 enhancer.setCallback(this);return enhancer.create();}/* (non-Javadoc) * @see org.springframework.cglib.proxy.MethodInterceptor#intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], org.springframework.cglib.proxy.MethodProxy) */public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//执行要代理的方法 System.out.print("记录日志"); //执行真正的方法, return method.invoke(target, args);}}

 ProductDAo的代码:

//没有接口,就不能使用JDK的动态代理,我们使用public class ProductDAo {    public void addProduct()    {        System.out.print("增加商品");            }    public void deleteProduct()    {                System.out.print("删除商品");            }}

 

JUnit的代码:

public class CglibProxyTest {@Testpublic void haveproxy(){
//1.创建目标对象 ProductDAo productDAo=new ProductDAo(); //2.创建代理类,因为没有接口所以这里使用ProductDAo proxy这么写的ProductDAo proxy=(ProductDAo)new CglibProxyFactory(productDAo).createProxy();proxy.addProduct();proxy.deleteProduct();}}

 

 

 

 

 

 

 

Cglib 创建代理思想: 对目标类创建子类对象

设置 superClass 对哪个类创建子类 (类似 JDK代理 接口)

设置 callback 实现增强代码 (类似 JDK代理 InvocationHandler

 

cglibcallback函数中,要执行被代理对象的方法

method.invoke(target, args); 等价于 methodProxy.invokeSuper(proxy, args); 

 

 

转载地址:http://yuqcx.baihongyu.com/

你可能感兴趣的文章
使用VMware安装CentOS7详请
查看>>
Ember.js 3.9.0-beta.3 发布,JavaScript Web 应用开发框架
查看>>
python标准库00 学习准备
查看>>
4.2. PHP crypt()
查看>>
Winform开发框架之附件管理应用
查看>>
软链接文件和硬链接文件
查看>>
Spring Cloud Config服务器
查看>>
commonservice-config配置服务搭建
查看>>
连接池的意义及阿里Druid
查看>>
ComponentOne 2019V1火热来袭!全面支持 Visual Studio 2019——亮点之WinForm篇
查看>>
全面的Spring Boot配置文件详解
查看>>
如何优雅地玩转分库分表
查看>>
Python递归函数与匿名函数
查看>>
我的友情链接
查看>>
CentOS添加永久静态路由
查看>>
mysql多实例的安装以及主从复制配置
查看>>
loadrunner安装运行一步一步来(多图)
查看>>
git请求报错 401
查看>>
动态追踪技术(四):基于 Linux bcc/BPF 实现 Go 程序动态追踪
查看>>
Cyber-Security: Linux 容器安全的十重境界
查看>>