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. PTA題目的處理(三)

    题目7-1 高速公路超速處罰 1.實驗代碼 #include <stdio.h> //#include <stdlib.h> int main() { int csp,lsp; ...

  2. networkx 学习

    import networkx as nx import pylab import numpy as np #自定义网络 row=np.array([,,,,,,]) col=np.array([,, ...

  3. 201621123031 《Java程序设计》第2周学习总结

    Week02-Java基本语法与类库 1. 本周学习总结 本周讲了Java的基本数据类型,主要分为八类(byte,short,int,long,double,float,char,boolean),其 ...

  4. 将数组写入Plist文件中

    -(void)writeToPlist:(NSArray *)uploadingfiles  Name:(NSString *)name {                  NSMutableArr ...

  5. 《高级软件测试》云平台Jira的配置

    首先点击进入以下网址: https://www.atlassian.com/ondemand/signup/form?product=jira-software.ondemand 填写好信息,Star ...

  6. 完美解决某法院HP EVA8400删除VDISK问题

    [故障描述] 某地法院一台HP EVA8400存储,2组扩展柜,物理磁盘由12个1T FATA磁盘(AG691A 454414-001)和10个300G 15K FC磁盘(AG690A 454411- ...

  7. 【微软大法好】VS Tools for AI全攻略

    大家都知道微软在Connect();17大会上发布了VS Tools for AI,旨在提升Visual Studio和VSCode对日益增长的深度学习需求的体验.看了一圈,网上似乎没有一个完整的中文 ...

  8. JAVA_SE基础——33.this关键字的练习

    需求:使用java定义的一个人类,人具备 id ,name ,age 三个属性,还具备一个比较年龄的方法. 要求:必须要写上构造函数,构造函数也必须要使用上this关键字. class Person{ ...

  9. java:多层文件夹情况下,判断文件夹下是否有文件夹,并获取到没有文件夹的名字的方法

    业务问题案例 在公司遇到的一个问题,本以为很小很好解决,没想到花了一下午时间.图给的是文件路径,page1下有10个文件夹,每个有的有文件夹或者文件,要求得到page1下(即:123456789,10 ...

  10. LeetCode & Q121-Best Time to Buy and Sell Stock-Easy

    Array DP Description: Say you have an array for which the ith element is the price of a given stock ...