-本想着这个知识点放到Spring Aop说说可能更合适一点,但因为上一篇有所提到就简单分析下,不足之处请多多评论留言,相互学习,有所提高才是关键!

什么是代理模式:

  记得有本24种设计模式的书讲到代理模式的经典例子,说的是西门庆、王婆、潘金莲的故事,比如西门庆找潘金莲,不好意思啊,则么办,找那个王婆做代理, 代理模式就是找个东西代替自己完成自己的活,这个就称之为代理。如宋哲经纪人,找房子中介......具体看看代码怎么写

区别

  • JDK动态代理只能对实现了接口的类生成代理,而不能针对类
  • CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承)

--JDK动态代理

  • 定义一个接口,保存和修改方法

    public interface UserDao {
    public void save();
    public void update(); }
    public class UserDaoImpl implements UserDao {
    
        @Override
    public void save() {
    System.out.println("sava doing .........");
    }
    @Override
    public void update() {
    System.out.println("update doing .........");
    } }
  • 测试一把:
    public class TestProxy {
    @Test
    public void run1(){
    //创建对象方式调用方法执行。
    UserDao dao = new UserDaoImpl();
    dao.save();
    dao.update(); System.out.println("============================="); }
    }
    sava doing .........
    update doing .........
    =============================
  • 加入代理模式   java.lang.reflect.Proxy
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy; import com.kk.Dao.UserDao;
    /**
    * 使用JDK的方式生成代理对象
    * @author Administrator
    */
    public class MyProxyUtils { public static UserDao getProxy(final UserDao dao) {
    // 使用Proxy类生成代理对象
    UserDao proxy = (UserDao) Proxy.newProxyInstance(dao.getClass().getClassLoader(),
    dao.getClass().getInterfaces(), new InvocationHandler() { // 代理对象方法一直线,invoke方法就会执行一次
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //在此可以利用代理对象来增强方法 比如在执行方法前记录一条日志。 当然进行权限校验,日志记录,性能监控,事务控制等都可以在此加强。这也是aop思想
    if("save".equals(method.getName())){
    System.out.println("记录日志...");
    }
    //让dao类的save或者update方法正常的执行下去
    UserDao invoke =(UserDao) method.invoke(dao, args);
    return invoke;
    }
    });
    // 返回代理对象
    return proxy;
    } }
  • 测试第二把:利用代理对象测试
    public class TestProxy {
    @Test
    public void run1(){
    UserDao dao = new UserDaoImpl();
    // 使用工具类,获取到代理对象
    UserDao proxy = MyProxyUtils.getProxy(dao);
    // 通过代理对象调用方法
    proxy.save();
    proxy.update();
    }
    }
    记录日志...
    sava doing .........
    update doing .........

由此可以看出来,在我方法执行前,我在没有改变原方法前加了一段记录日志/代码,这就是一种aop思想,降低代码耦合度。

CGLIB代理方式:

  • 加入cglib-2.2.2.jar: 及三方依赖  asm-3.3.1.jar

  • 编写BookDaoImpl实现类

    public class BookDaoImpl {
    public void save() {
    System.out.println("sava doing .........");
    }
    public void update() {
    System.out.println("update doing .........");
    }
    }
  • CGLIB创建代理方式工具类
    package com.kk.Utils;
    import java.lang.reflect.Method; import com.kk.DaoImpl.BookDaoImpl;
    import com.kk.DaoImpl.UserDaoImpl; import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy; public class MyCglibUtils { /**
    * 使用CGLIB方式生成代理的对象
    *
    * @return
    */
    public static BookDaoImpl getProxy( BookDaoImpl bookDaoImpl) {
    Enhancer enhancer = new Enhancer();
    // 设置父类
    enhancer.setSuperclass(bookDaoImpl.getClass());
    // 设置回调函数
    enhancer.setCallback(new MethodInterceptor() {
    // 代理对象的方法执行,回调函数就会执行
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    if(method.getName().equals("save")){
    System.out.println("记录日志...");
    }
    // 正常执行
    return methodProxy.invokeSuper(obj, args);
    }
    });
    // 生成代理对象
    BookDaoImpl proxy = (BookDaoImpl) enhancer.create();
    return proxy;
    }
    }
  • 测试一把:
    @Test
    public void run1(){
    //目标对象
    BookDaoImpl dao = new BookDaoImpl();
    // 通过代理对象调用方法
    dao.save();
    dao.update();
    System.out.println("================================");
    BookDaoImpl proxy = MyCglibUtils.getProxy(dao);
    proxy.save();
    proxy.update();
    } sava doing .........
    update doing .........
    ================================
    记录日志...
    sava doing .........
    update doing .........

    同理:通过代理对象可以帮我们完成代码增强等功能,注意:JDK代理是通过接口模式,而CGLIB则通过实现类方式帮我们创建代理对象。后期Spring会更深了解。

    Spring在选择用JDK还是CGLiB的依据:

  • 当Bean实现接口时,Spring就会用JDK的动态代理
  • 当Bean没有实现接口时,Spring使用CGlib是实现
  • 可以强制使用CGlib(在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)

  CGlib比JDK快?

  • 使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。
  • 在对JDK动态代理与CGlib动态代理的代码实验中看,1W次执行下,JDK7及8的动态代理性能比CGlib要好20%左右。

  

java设计模式(一)动态代理模式,JDK与CGLIB分析的更多相关文章

  1. Java中的动态代理(jdk和cglib)

    JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类 ...

  2. Java设计模式—Proxy动态代理模式

    代理:设计模式 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 图 1. 代 ...

  3. 代理设计模式 (静态代理设计模式)+ 动态代理(JDK和Cglib)

    一.代理设计模式 1.设计模式:前人总结一套解决特定问题的代码 2.代理设计模式优点: 2.1 保护真实对象 2.2 让真实对象职责更明确 2.3 扩展 3.代理设计模式 3.1 真实对象(老总) 3 ...

  4. [转]java动态代理(JDK和cglib)

    转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html java动态代理(JDK和cglib) JAVA的动态代理 代理模式 代理 ...

  5. java设计模式之Proxy(代理模式)

    java设计模式之Proxy(代理模式) 2008-03-25 20:30 227人阅读 评论(0) 收藏 举报 设计模式javaauthorizationpermissionsstringclass ...

  6. Java设计模式之《代理模式》及应用场景

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6525527.html 代理模式算是我接触较早的模式,代理就是中介,中间人.法律上也有代理, ...

  7. Java的三种代理模式&完整源码分析

    Java的三种代理模式&完整源码分析 参考资料: 博客园-Java的三种代理模式 简书-JDK动态代理-超详细源码分析 [博客园-WeakCache缓存的实现机制](https://www.c ...

  8. Java 的静态代理 动态代理(JDK和cglib)

    转载:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是 ...

  9. java的静态代理和动态代理(jdk、cglib)

    一.代理模式 代理的概念来自于设计模式中的代理模式,先了解一下代理模式 1.结构图 2.参与者 Subject:接口,定义代理类和实际类的共用接口 RealSubject:实际类,实现Subject这 ...

  10. java动态代理(JDK和cglib)

    转:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代 ...

随机推荐

  1. ubuntu 16.04上源码编译libjpeg-turbo和使用教程 | compile and use libjpeg-turbo on ubuntu 16.04

    本文首发于个人博客https://kezunlin.me/post/9f626e7a/,欢迎阅读! compile and use libjpeg-turbo on ubuntu 16.04 Seri ...

  2. Spring Boot 2.X(十八):集成 Spring Security-登录认证和权限控制

    前言 在企业项目开发中,对系统的安全和权限控制往往是必需的,常见的安全框架有 Spring Security.Apache Shiro 等.本文主要简单介绍一下 Spring Security,再通过 ...

  3. IDEA用Maven连接MySQL的jdbc驱动,并操作数据库

    1.在IDEA里创建Maven项目 1.1.点击Create New Project   1.2.选择Maven,JDK这里用的是1.8,点击Next  1.3.填入“组织名”.“项目名”,版本是默认 ...

  4. 2019-9-29,php基础学习,笔记

    cobalt strike简单使用cobalt是一个后渗透测试工具,基于java开发,适用于团队间协同作战,简称"cs"cs分为客户端和服务端,一般情况下我们称服务端为团队服务器, ...

  5. Lab4\5:进程和线程

    进程的定义 进程是指一个具有一定独立功能的程序在一个数据集合上的一次动态执行过程 源代码在经过编译链接之后生成了可执行文件,再由操作系统进行加载并且进行一些堆栈的分配才是进程 进程控制块 操作系统管理 ...

  6. App自动化测试-1.App自动化介绍和环境搭建

    App自动化测试-1.App自动化介绍和环境搭建 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-b ...

  7. yum运行报错:/usr/lib64/python2.7/site-packages/pycurl.so: undefined symbol: CRYPTO_num_locks

    是因为yum动态库使用了新安装libcurl库导致的.使用ldd查看动态库依赖关系: ldd /usr/lib64/python2.7/site-packages/pycurl.so 删除动态库配置中 ...

  8. 使用 colgroup 和 col 实现响应式表格

    Table 在项目使用中十分频繁,特别是在后台管理系统中,table 无疑是数据展示的第一公民,在早些年的网页中,table 也是网页布局的第一选择,然后使用好 table 并不容易,其它有很多子元素 ...

  9. tcp协议传输方法&粘包问题

    socket实现客户端和服务端 tcp协议可以用socket模块实现服务端可客户端的交互 # 服务端 import socket #生成一个socket对象 soc = socket.socket(s ...

  10. JDK官方下载

    平时进行java开发时避免不了使用jdk,而现在jdk版本已经到1.9了,但是之前版本下载在官方网站就不好找了(主要还是因为网站是英文的): 进入官网下载jdk的前提是进入官网,直接百度搜jdk下载也 ...