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. Algorithm --> 阶乘和因子

    阶乘和因子 要求:输入正整数n(1<n <101), 把阶乘n!=1x2x3x...xn分解成素因子相乘的形式,从小到大输出各个素数(2,3,5,...)的指数. 例如825=3x52x1 ...

  2. pycharm 的安装及selenium环境的搭建

    6.呵呵哒,前面写了一篇pycharm的安装,,结果自己都看不懂了,copy了别人的,,,自己现在再写一遍,这篇文章主要写pycharm 的安装及selenium 环境的搭建,selenium的搭建不 ...

  3. java排序算法(一):概述

    java排序算法(一)概述 排序是程序开发中一种非常常见的操作,对一组任意的数据元素(活记录)经过排序操作后,就可以把它们变成一组按关键字排序的一组有序序列 对一个排序的算法来说,一般从下面三个方面来 ...

  4. heartbeat错误排查

    错误一: [root@snale2 ha.d ::]#service heartbeat start Starting High-Availability services: INFO: Resour ...

  5. ssh框架-Struts2(一)

    Struts2 概述 用我们自己的话来说: struts是web层框架, 相当于Servlet 作用: 1. 获得请求参数 2. 调用业务 3. 分发转向 常用的WEB层框架 Struts2入门 1. ...

  6. JavaScript(第二十九天)【js处理XML】

    随着互联网的发展,Web应用程序的丰富,开发人员越来越希望能够使用客户端来操作XML技术.而XML技术一度成为存储和传输结构化数据的标准.所以,本章就详细探讨一下JavaScript中使用XML的技术 ...

  7. oracle创建表空间、创建用户并赋予权限

    分开执行如下sql语句 --创建临时表空间 CREATE SMALLFILE TEMPORARY TABLESPACE "TEMP11" TEMPFILE 'E:\app\MD\o ...

  8. Flask 扩展 国际化 本地化

    pip install flask-babel 先初始化一个Flask-Babel的实例 from flask import Flask from flask.ext.babel import Bab ...

  9. 20162302 实验一《Java开发环境的熟悉》实验报告

    实 验 报 告 课程:程序设计与数据结构 姓名:杨京典 班级:1623 学号:20162302 实验名称:Java开发环境的熟悉 实验器材:装有Ubuntu的联想拯救者80RQ 实验目的与要求:1.使 ...

  10. python每日一函数 - divmod数字处理函数

    python每日一函数 - divmod数字处理函数 divmod(a,b)函数 中文说明: divmod(a,b)方法返回的是a//b(除法取整)以及a对b的余数 返回结果类型为tuple 参数: ...