静态代理和利用反射形成的动态代理(JDK动态代理)
代理模式
代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
静态代理
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动态代理)的更多相关文章
- JDK动态代理深入理解分析并手写简易JDK动态代理(下)
原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-05/27.html 作者:夜月归途 出处:http://www.guitu ...
- JDK动态代理深入理解分析并手写简易JDK动态代理(上)
原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-03/27.html 作者:夜月归途 出处:http://www.guitu ...
- 【原创】分布式之缓存击穿 【原创】自己动手实现静态资源服务器 【原创】自己动手实现JDK动态代理
[原创]分布式之缓存击穿 什么是缓存击穿 在谈论缓存击穿之前,我们先来回忆下从缓存中加载数据的逻辑,如下图所示 因此,如果黑客每次故意查询一个在缓存内必然不存在的数据,导致每次请求都要去存储层去查 ...
- 动态代理学习(一)自己动手模拟JDK动态代理
最近一直在学习Spring的源码,Spring底层大量使用了动态代理.所以花一些时间对动态代理的知识做一下总结. 我们自己动手模拟一个动态代理 对JDK动态代理的源码进行分析 文章目录 场景: 思路: ...
- 代理模式 静态代理、JDK动态代理、Cglib动态代理
1 代理模式 使用代理模式时必须让代理类和被代理类实现相同的接口: 客户端通过代理类对象来调用被代理对象方法时,代理类对象会将所有方法的调用分派到被代理对象上进行反射执行: 在分派的过程中还可以添加前 ...
- java的静态代理、jdk动态代理和cglib动态代理
Java的代理就是客户端不再直接和委托类打交道,而是通过一个中间层来访问,这个中间层就是代理.使用代理有两个好处,一是可以隐藏委托类的实现:二是可以实现客户与委托类之间的解耦,在不修改委托类代码的情况 ...
- 从静态代理,jdk动态代理到cglib动态代理-一文搞懂代理模式
从代理模式到动态代理 代理模式是一种理论上非常简单,但是各种地方的实现往往却非常复杂.本文将从代理模式的基本概念出发,探讨代理模式在java领域的应用与实现.读完本文你将get到以下几点: 为什么需要 ...
- 静态代理与JDK动态代理
demo地址: https://github.com/ZbLeaning/leaning 代理: 为其他对象提供一种代理以控制对这个对象的访问.分为静态代理和动态代理.代理模式的目的就是为真实业务对象 ...
- 代理模式(静态代理、JDK动态代理原理分析、CGLIB动态代理)
代理模式 代理模式是设计模式之一,为一个对象提供一个替身或者占位符以控制对这个对象的访问,它给目标对象提供一个代理对象,由代理对象控制对目标对象的访问. 那么为什么要使用代理模式呢? 1.隔离,客户端 ...
随机推荐
- C#日志
参考页面: http://www.yuanjiaocheng.net/Entity/first.html http://www.yuanjiaocheng.net/Entity/jieshao.htm ...
- PHP设计模式(二)工厂方法模式(Factory Method For PHP)
简单工厂简述: 简单工厂模式实现了生产产品类的代码跟客户端代码分离,在工厂类中你可以添加需要生成长跑的逻辑代码(new 产品类),但是问题来了,优秀的代码是符合"开闭原则"如果你要 ...
- hibernate的基本xml文件配置
需要导入基本的包hibernate下的bin下的required和同bin下optional里的c3p0包下的所有jar文件,当然要导入mysql的驱动包了.下面需要注意的是hibernate的版本就 ...
- swift 可选类型(optional)--- swift 入门
一.思维导图 二.代码 //这样无形中就会让代码很丑陋 if x != nil && y != nil { print("x或y都不等于空") } print(&q ...
- [bzoj2152][聪聪和可可] (点分治+概率)
Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好 ...
- Kafka1 利用虚拟机搭建自己的Kafka集群
前言: 上周末自己学习了一下Kafka,参考网上的文章,学习过程中还是比较顺利的,遇到的一些问题最终也都解决了,现在将学习的过程记录与此,供以后自己查阅,如果能帮助到其他人,自然是更好的. ...
- Windbg Extension NetExt 使用指南 【3】 ---- 挖掘你想要的数据 Managed Heap
摘要 : NetExt中有两个比较常用的命令可以用来分析heap上面的对象. 一个是!wheap, 另外一个是!windex. !wheap 这个命令可以用于打印出heap structure信息. ...
- 内网穿透神器ngrok
相信做Web开发的同学们,经常会遇到需要将本地部署的Web应用能够让公网环境直接访问到的情况,例如微信应用调试.支付宝接口调试等.这个时候,一个叫ngrok的神器可能会帮到你,它提供了一个能够在公网安 ...
- Sublime Text3使用总结
写在前面的话:平时做项目中在用eclipse和vs,但是对于一些小项目,感觉没有必要搞那么大的一个工具使用,比如写个小微商城,搞个小脚本了什么,所以就一直在用Sublime Text,界面清新简洁,没 ...
- TODO:这是一个我的自媒体
TODO:这是一个我的自媒体 自媒体(外文名:We Media)又称"公民媒体"或"个人媒体",是指私人化.平民化.普泛化.自主化的传播者,以现代化.电子化的手 ...