静态代理和利用反射形成的动态代理(JDK动态代理)

时间:2022-05-20 22:43:50

代理模式

代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

静态代理

1.新建一个接口,这个接口所提供的方法是关于数据库操作的

public interface EmployeeDao {
public void updateSalary();
}

2.建一个目标类实现这个接口,这个目标类是我们要进行的业务

public class EmployeeDaoImpl implements EmployeeDao {
@Override
public void updateSalary() {
System.out.println("您的薪水又有更新");
}
}

3.再建一个代理类,为目标对象提供一种代理,并以控制对这个对象的访问。

public class EmployeeDaoProxy implements EmployeeDao{
private EmployeeDao employeeDao;
private Transaction transaction;
public EmployeeDaoProxy(EmployeeDao employeeDao,Transaction transaction) {
this.employeeDao=employeeDao;
this.transaction=transaction;
} @Override
public void updateSalary() {
this.transaction.startTransaction();
this.employeeDao.updateSalary();
this.transaction.commit();
}

由以上的代码可知:

代理模式的组成包括:目标接口(抽象角色),目标类(真实角色)和代理类(代理角色)。

  • 抽象角色:通过接口声明真实角色实现的业务方法。
  • 代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作
  • 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

4.代理类代理事务的处理,所以需要增加一个事务类


public class Transaction {
public void startTransaction(){
System.out.println("开启事务");
}
public void commit(){
System.out.print("事物提交");
}
}

5.最后我们用一个test case来测试一下


import static org.junit.Assert.*;
import org.junit.Test;
public class ProxyTest {
@Test
public void test() {
EmployeeDao target = new EmployeeDaoImpl();
Transaction transaction = new Transaction();
EmployeeDao proxy = new EmployeeDaoProxy(target,transaction);
proxy.updateSalary();
}
}

假设上面的例子中的接口不只一个方法,或是不只一个接口要用到代理,上面的静态代理的代码就太过繁琐和冗余,所以就出现了jdk的动态代理。

看一下执行情况

开启事务
您的薪水又有更新
事物提交
利用反射动态代理

反射机制指的是程序在运行时能够获取自身的信息。这里的反射一开始不太好理解,其实应该忽略反射的字面意思。只要知道反射其实就是获取Class对象,然后反编译程Java对象,然后访问Java对象的属性、方法等。在Java中,其实所有类的对象都是Class类的实例。每个类被JVM加载之后,就会生成对应对应的Class对象。获得Class对象的方式有以下三种:

1.使用Class类的forName(String className)静态方法,className为类的全名。

Class = Class.forName("Employee");

2.调用某个类的class属性

Class = Employee.class

3.调用某个对象的getClass方法

Employee ee = new Employee();
Class = ee.getClass();

可以从Class中获取的信息包括:构造器、方法、Annotation、内部类、所实现的接口、所继承的父类、对应类的修饰符,所在包类名等基本信息。除此之外,Class对象还可以判断该类是否为接口、枚举、注解类型。再回到上面的代理模式,在JDK中提供Proxy类和InvocationHandler接口生成JDK动态代理类和动态代理对象,Proxy是所有动态代理类的父类,提供创建动态代理类和代理对象的静态方法。

1.创建动态代理类的方法

static Class<?> getProxyClass(ClassLoader loader,Class<?>[]interfaces)

2.创建动态代理实例的方法

static ObjectnewProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler)

同样以上面的例子做示例,1和2中的接口和目标类的编写以及4中的事务处理是相同的,在3中,我们引入拦截器,拦截器是实现动态性的核心

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; /*
* 拦截器
* 引入目标类和事务
* 通过构造器给目标函数和事务赋值
* 填充invoke方法
*
*/
public class EmployeeInterceptor implements InvocationHandler{
private Object target;
private Transaction transaction;
public EmployeeInterceptor(Object target, Transaction transaction) { this.target = target;
this.transaction = transaction;
} /*
* proxy:代表动态代理对象
* method:代表正在执行的方法
* args:代表调用方法是传入的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
this.transaction.startTransaction();
method.invoke(this.target, args);
this.transaction.commit();
return null;
}
}

同样在test case中测试一下:


import static org.junit.Assert.*;
import java.lang.reflect.Proxy;
import org.junit.Test;
public class ProxyTest1 {
@Test
public void test() {
EmployeeDao target = new EmployeeDaoImpl();
Transaction transaction = new Transaction();
EmployeeInterceptor interceptor = new EmployeeInterceptor(target,transaction);
//利用Proxy创建动态代理类
EmployeeDao employeeDao = (EmployeeDao)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), interceptor);
employeeDao.updateSalary();
}
}

最后看一下执行的情况

开启事务
您的薪水又有更新
事物提交

静态代理和利用反射形成的动态代理(JDK动态代理)的更多相关文章

  1. JDK动态代理深入理解分析并手写简易JDK动态代理(下)

    原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-05/27.html 作者:夜月归途 出处:http://www.guitu ...

  2. JDK动态代理深入理解分析并手写简易JDK动态代理(上)

    原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-03/27.html 作者:夜月归途 出处:http://www.guitu ...

  3. 【原创】分布式之缓存击穿 【原创】自己动手实现静态资源服务器 【原创】自己动手实现JDK动态代理

    [原创]分布式之缓存击穿   什么是缓存击穿 在谈论缓存击穿之前,我们先来回忆下从缓存中加载数据的逻辑,如下图所示 因此,如果黑客每次故意查询一个在缓存内必然不存在的数据,导致每次请求都要去存储层去查 ...

  4. 动态代理学习(一)自己动手模拟JDK动态代理

    最近一直在学习Spring的源码,Spring底层大量使用了动态代理.所以花一些时间对动态代理的知识做一下总结. 我们自己动手模拟一个动态代理 对JDK动态代理的源码进行分析 文章目录 场景: 思路: ...

  5. 代理模式 静态代理、JDK动态代理、Cglib动态代理

    1 代理模式 使用代理模式时必须让代理类和被代理类实现相同的接口: 客户端通过代理类对象来调用被代理对象方法时,代理类对象会将所有方法的调用分派到被代理对象上进行反射执行: 在分派的过程中还可以添加前 ...

  6. java的静态代理、jdk动态代理和cglib动态代理

    Java的代理就是客户端不再直接和委托类打交道,而是通过一个中间层来访问,这个中间层就是代理.使用代理有两个好处,一是可以隐藏委托类的实现:二是可以实现客户与委托类之间的解耦,在不修改委托类代码的情况 ...

  7. 从静态代理,jdk动态代理到cglib动态代理-一文搞懂代理模式

    从代理模式到动态代理 代理模式是一种理论上非常简单,但是各种地方的实现往往却非常复杂.本文将从代理模式的基本概念出发,探讨代理模式在java领域的应用与实现.读完本文你将get到以下几点: 为什么需要 ...

  8. 静态代理与JDK动态代理

    demo地址: https://github.com/ZbLeaning/leaning 代理: 为其他对象提供一种代理以控制对这个对象的访问.分为静态代理和动态代理.代理模式的目的就是为真实业务对象 ...

  9. 代理模式&lpar;静态代理、JDK动态代理原理分析、CGLIB动态代理&rpar;

    代理模式 代理模式是设计模式之一,为一个对象提供一个替身或者占位符以控制对这个对象的访问,它给目标对象提供一个代理对象,由代理对象控制对目标对象的访问. 那么为什么要使用代理模式呢? 1.隔离,客户端 ...

随机推荐

  1. android应用安全——(数据抓包)跟踪监控android数据包

    转载博客:http://blog.csdn.net/xyz_lmn/article/details/8808169 web开发中Chrome.IE.firefox等浏览器都自带提供了插件帮助开发者跟踪 ...

  2. Git 源代码管理工具

    Git 源代码管理工具 Git基本信息 Git :Git是一个“分布式”的版本控制工具 Git的作者是Linux之父 Linus Benedict Torvolds,当初开发Git仅仅是为了辅助Lin ...

  3. LPC43xx Dual-core or Multi-core configuration and JLink Debug

    Test access port (TAP) JTAG defines a TAP (Test access port). The TAP is a general-purpose port that ...

  4. const C语言(转)

    const在C语言中算是一个比较新的描述符,我们称之为常量修饰符,意即其所修饰的对象为常量(immutable). 我们来分情况看语法上它该如何被使用. 1.函数体内修饰局部变量.例:void fun ...

  5. 如何快速查看将C反汇编的代码

    查看反汇编主要的思路在于将 流程,处理,算法 区分开来.1 函数调用:原C代码: int sum(int, int);int main(){ int c = sum(1, 2); printf(&qu ...

  6. hibernate三级缓存介绍

    hibernate缓存机制:分为三种:1.一级缓存(session级别缓存,同一session中不会重复发出sql,默认会实现)2.二级缓存(跨session的缓存,不同session会从同一缓存中取 ...

  7. 基于 libevent 开源框架实现的 web 服务器

    /* 原创文章 转载请附上原链接: https://www.cnblogs.com/jiujue/p/10707153.html   */ 自己实现的如有缺漏欢迎提出 直接代码 一切皆在代码中 首先是 ...

  8. Jenkins与sonar扫描的集成问题

    记录本周遇到的头疼了很久的一个问题,由于公司需要使用jenkins来自动管理构建项目,然后在关联sonar对项目代码质量进行审核. 接着坑爹的问题来了,原有的技术手段为项目构建成功后通过jenkins ...

  9. ViewBag赋值Html格式值

    今天再给自己总结一下,关于ViewBag赋值Html格式值,但是在web页显示不正常; 例如,ViewBag.Content = "<p>你好,我现在测试一个东西.</p& ...

  10. scp 免密登录ssh-copy-id 如何使用非22端口 &plus; rsync 同步远程机器的文件到本地

    其中:id_rsa为私钥文件,id_rsa.pub为公钥文件 ssh-copy-id  -i ~/.ssh/id_rsa.pub  "-p 2122  root@IP " 我的:s ...