java常用的设计模式详解:

1.代理模式(JDK的动态代理)

【IDept.java】

​ 这是一个简单的就接口,进行数据的更新

package com.itcloud.pattern.proxy;

public interface IDept {
void update();
}

【DeptImp.java】

​ Dept的实现类

package com.itcloud.pattern.proxy;

public class DeptImpl implements IDept {
@Override
public void update() {
System.out.println("完成核心功能,进行数据的更新操作");
}
}

【InvoProxy.java】

​ 代理类,被代理对象只需要完成核心功能,而其他的功能都由代理对象完成

package com.itcloud.pattern.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class InvoProxy implements InvocationHandler { private Object obj; // 首先要获取代理对象 public Object getProxyInterface(Object obj) {
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
} /**
实现的基本步骤
1.获取代理类对象,然后获取其接口
2.生成新的类,实现代理类的接口,这个类其实只是字节码文件
3.在新生成的类中进行代码的执行
*/ @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("数据库开启事物");// 这些事情由代理类完成
try {
return method.invoke(this.obj, args); // 代理类完成核心功能
} catch (Exception e) { } finally {
System.out.println("进行事物的回滚操作");
}
return null;
}
}

【TestDemo.java】

public class TestDemo {
public static void main(String[] args) {
IDept dept = (IDept)new InvoProxy().getProxyInterface(new DeptImpl());
dept.update();
}
}
//测试结果
/*
数据库开启事物
完成核心功能,进行数据的更新操作
进行事物的回滚操作
*/

在代码中我们说过,代理对象会生成一个代理类,那么我们来看一下这个类究竟长什么样

首先在测试类中将字节码写入本地文件

【TestDemo.java】

import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;

public class TestDemo {
public static void main(String[] args) throws Exception {
IDept dept = (IDept)new InvoProxy().getProxyInterface(new DeptImpl());
dept.update();
byte[] $Proxy0 = ProxyGenerator.generateProxyClass("$Proxy0", new Class<?>[]{IDept.class});
FileOutputStream out = new FileOutputStream("G:\\$Proxy0.class");
out.write($Proxy0);
out.close();
}
}

我们可以在g盘中生成一个$Proxy0.class文件,这个文件就是类的字节码文件,你看不懂我也看不懂这时候需要借用反编译软件(jd-gui-0.3.6),进行反编译

【$Proxy0.class】

import com.itcloud.pattern.proxy.IDept;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException; public final class $Proxy0
extends Proxy
implements IDept
{
private static Method m1;
private static Method m2;
private static Method m0;
private static Method m3; public $Proxy0(InvocationHandler paramInvocationHandler)
throws
{
super(paramInvocationHandler);
} public final boolean equals(Object paramObject)
throws
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
} public final String toString()
throws
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
} public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
} public final Boolean update()
throws
{
try
{
return (Boolean)this.h.invoke(this, m3, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
} static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m3 = Class.forName("com.itcloud.pattern.proxy.IDept").getMethod("update", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}

总结:jdk动态代理必须要有接口

3.cglib代理

cglib中,被代理对象不需要继承相关接口

【pom.xml】文件中添加依赖

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

【Student.java】

package com.itcloud.pattern.cglib;
public class Student { public void update() {
System.out.println("进行数据的更新操作");
}
}

【CglibProxy.java】

package com.itcloud.pattern.cglib;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; public class CglibProxy implements MethodInterceptor { //获取代理类的对象
public Object getInstance(Class<?> clazz) {
Enhancer enhancer = new Enhancer();
enhancer.setCallback(this);
enhancer.setSuperclass(clazz);//设置生成代理类的父类
//enhancer.create()这个方法会创建com.itcloud.pattern.cglib.Student$$EnhancerByCGLIB$$4c126679@20e2cbe0代理类,这个代理类是被代理类的子类
return enhancer.create();//enhancer.create() instanceof Student 返回结果true
} /**
*
* @param obj cglib生成的代理类
* @param method 被代理对象中的方法
* @param args 方法的参数
* @param methodProxy 代理方法,即生成代理类中的方法
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("数据更新前,事物开启"); try {
return methodProxy.invokeSuper(obj, args);//明确调用父类中的方法
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("出现异常,事物回滚,rollback");
}
return null;
}
}

此时我们也可以像JDK动态代理那样对生成的代理类进行字节码反编译。

爱生活爱分享欢迎您的关注与加入自学交流群:461265466

一、spring的成长之路——代理设计模式的更多相关文章

  1. 二·、spring成长之路——委派设计模式和单例设计模式

    3.委派设计模式 设计思想:就是多个类去完成一项的工作,其中一个类去分发任务,其他类做具体的任务,而具体表现是这个委派类的工作,具体过程是被委派类来操作的 [ITask.java]定义工作的统一标准 ...

  2. Spring Boot 成长之路(一) 快速上手

    1.创建工程 利用IntelliJ IDEA新建一个Spring Boot项目的Web工程 2.查看初始化的spring boot项目 工程建好之后会出现如下的目录结构: 值得注意的第一件事是,整个项 ...

  3. Spring知识点总结(四)之SpringAOP基础 - 代理设计模式

        1. 分析程序中存在的问题(高内聚,低耦合)        通过springIOC DI) 以及注解的使用,成功解决了在程序中层与层之间出现的耦合的问题,但是在很多地方仍然存在非该层应该实现的 ...

  4. Spring(八)-- 代理设计模式

    代理设计模式 1:基本概念 2:JDK动态代理 1. 创建接口 2. 创建实现类 3. 创建代理类 /** * jdk动态代理 不能满足 继承父类的情况 * * AnimalProxy 代理类 */ ...

  5. java 成长之路[轉載u]

    分享总结title: java 成长之路tags:grammar_cjkRuby: true 经验差异 1-3年 要求 建议 3-5年 建议 5年+ 经验差异 最近一年比较忙,经历了创业公司的倒闭.这 ...

  6. java 成长之路

    分享总结 title: java 成长之路 tags: grammar_cjkRuby: true 经验差异 1-3年 要求 建议 3-5年 建议 5年+ 经验差异 最近一年比较忙,经历了创业公司的倒 ...

  7. Web前端工程师成长之路

    一.何为Web前端工程师?        前端工程师,也叫Web前端开发工程师.他是随着web发展,细分出来的行业.Web前端开发工程师,主要职责是利用(X)HTML/CSS/JavaScript/D ...

  8. --专访雷果国: 从1.5K到18K 一个程序员的5年成长之路--

    导语:今年三月份,在CSDN博客和新浪微博上有一篇<从1.5K到18K,一个程序员的5年成长之路>被众人分享和传阅,这篇博文首先介绍了作者自学之初薄弱的基础,然后通过流水账形式分享了那个从 ...

  9. linux小白成长之路10————SpringBoot项目部署进阶

    [内容指引] war包部署: jar包部署: 基于Docker云部署. 一.war包部署 通过"云开发"平台初始化的SpringBoot项目默认采用jar形式打包,这也是我们推荐的 ...

随机推荐

  1. linux --> 动态库和静态库

    库的分类 根据链接时期的不同,库分为静态库和动态库之分. 静态库:在链接阶段被链接的,生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. 动态库:在程序执行的时候被链接的,即使程 ...

  2. IE11,Chrome65.0.3325.146,Firefox58的webdriver驱动下载,并用selenium驱动来实现自动化测试

    各浏览器版本:    python版本: selenium版本: IE11的Webdriver下载: http://dl.pconline.com.cn/download/771640-1.html ...

  3. 火狐浏览器中如何删除保存的cookie

    大致分为三步即可: 打开浏览器并查看图示,按照图示操作即可完成:

  4. 仿京东树形菜单插件hovertree

    hovertree是一个仿京东的树形菜单jquery插件,暂时有银色和绿色两种. 官方网址:http://keleyi.com/jq/hovertree/欢迎下载使用 查看绿色效果:http://ke ...

  5. 【Redis使用系列】Redis常用操作

    一.string类型的常用命令 set key value   #一个key对应一个value.多次赋值,会覆盖前面. setnx key value  #如果key存在则创建key1,并返回1,如果 ...

  6. Beta No.7

    今天遇到的困难: 构造新适配器的时候出现了某些崩溃的问题 ListView监听器有部分的Bug 今天完成的任务: 陈甘霖:完成相机调用和图库功能,完成阿尔法项目遗留下来的位置调用问题,实现百度定位 蔡 ...

  7. 需求分析&原型改进

    需求&原型改进 一.给目标用户展现原型,与目标用户进一步沟通理解需求. 1.用户痛点:需要随时随地练习四则运算,并能看到用户的统计数据. 2.用户反馈:较好地解决练习需求,若能加入班级概念则更 ...

  8. mongodb 集群分片

    分片 在Mongodb里面存在另一种集群,就是分片技术,可以满足MongoDB数据量大量增长的需求 当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量,这 ...

  9. 20145237《Java程序设计》实验报告一

    实验一 Java开发环境的熟悉(Windows + Eclipse) 实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用Eclipse 编辑.编译.运行.调试Java程序. 实验要求 1 ...

  10. Python科学计算(一)

    作者 J.R. Johansson (robert@riken.jp) http://dml.riken.jp/~rob/ 最新版本的 IPython notebook 课程文件 http://git ...