【SSH系列】静态代理&&动态代理
从设计模式说起
代理模式是二十三中设计模式中的一种,代理模式就是指由一个代理主题来操作真实的主题,真实的主题执行具体的业务操作,而代理主题负责其她相关业务,简而言之,代理模式可以由以下三个部分组成:
a、抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
b、代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
c、真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
第一次接触代理模式的是在学习大话设计模式的时候,首先,小编带着小伙伴们一起回顾一下代理模式:
概念:
为其他对象提供一种代理以控制对这个对象的访问,代理是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,我们也许有代理服务器等概念,代理概念可以解释为:在出发点到目的地之间有一道中间层,意为代理。
uml图
生活中的代理
当客户端需要调用某个对象时,客户端实际上也不关心是否准确得到该对象,她只要一个能提供该功能的对象即可,此时我们就可返回该对象的代理。 看到此处,相信读者应该对Spring的AOP框架有点感觉了:当Spring容器中的被代理Bean实现了一个或多个接口时,Spring所创建的AOP代理就是这种动态代理。Spring AOP与此示例应用的区别在哪里呢?Spring AOP更灵活,当Sping定义InvocationHandler类的invoke()时,它并没有以硬编码方式决定调用哪些拦截器,而是通过配置文件来决定在invoke()方法中要调用哪些拦截器,这就实现了更彻底的解耦——当程序需要为目标对象扩展新功能时,根本无须改变Java代理,只需要在配置文件中增加更多的拦截器配置即可。
代理的分类
a、静态代理
由程序员创建或工具生成代理类的源码,再编译代理类,所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
b、 动态代理
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。
接着,小编分别讲解一下静态代理&&动态代理,加上相关的demo,希望可以帮助到有需要的小伙伴。
静态代理
具体用户管理实现类
package com.bjpowernode.spring;
public class UserManagerImpl implements UserManager {
public void addUser(String username, String password) {
//checkSecurity();
System.out.println("---------UserManagerImpl.add()--------");
}
public void delUser(int userId) {
//checkSecurity();
System.out.println("---------UserManagerImpl.delUser()--------");
}
public String findUserById(int userId) {
//checkSecurity();
System.out.println("---------UserManagerImpl.findUserById()--------");
return "张三";
}
public void modifyUser(int userId, String username, String password) {
//checkSecurity();
System.out.println("---------UserManagerImpl.modifyUser()--------");
}
// private void checkSecurity() {
// System.out.println("-------checkSecurity-------");
// }
}
代理类--代理用户管理实现类
package com.bjpowernode.spring;
public class UserManagerImplProxy implements UserManager {
private UserManager userManager;
public UserManagerImplProxy(UserManager userManager) {
this.userManager = userManager;
}
public void addUser(String username, String password) {
checkSecurity();
userManager.addUser(username, password);
}
public void delUser(int userId) {
checkSecurity();
userManager.delUser(userId);
}
public String findUserById(int userId) {
checkSecurity();
return userManager.findUserById(userId);
}
public void modifyUser(int userId, String username, String password) {
checkSecurity();
userManager.modifyUser(userId, username, password);
}
private void checkSecurity() {
System.out.println("-------checkSecurity-------");
}
}
客户端调用
package com.bjpowernode.spring;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
SecurityHandler hander = new SecurityHandler();
UserManager useraManager = (UserManager)hander.createProxyInstance(new UserManagerImpl());
useraManager.addUser("张三", "123");
}
}
ok,结合代码部分,具体说说静态代理,代理使客户端不需要知道实现类是什么,怎么做的,而客户端只需知道代理即可(解耦合),对于如上的客户端代码,newUserManagerImpl()可以应用工厂将它隐藏。接着继续讲解动态代理。
动态代理
通过上面的demo,一个代理只能代理一个类型,而且是在编译器就已经确定被代理的对象。而动态代理实在运行的时候,通过反射机制来实现动态代理,并且能够代理各种类型的对象。在java中要想实现动态代理机制,需要java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy 类的支持,接着我们来编写具体的代码部分。
具体实现类,代码如下所示:
package com.bjpowernode.spring;
public class UserManagerImpl implements UserManager {
public void addUser(String username, String password) {
//checkSecurity();
System.out.println("---------UserManagerImpl.add()--------");
}
public void delUser(int userId) {
//checkSecurity();
System.out.println("---------UserManagerImpl.delUser()--------");
}
public String findUserById(int userId) {
//checkSecurity();
System.out.println("---------UserManagerImpl.findUserById()--------");
return "张三";
}
public void modifyUser(int userId, String username, String password) {
//checkSecurity();
System.out.println("---------UserManagerImpl.modifyUser()--------");
}
}
动态创建代理对象的类
根据如上的介绍,你会发现每个代理类只能为一个接口服务,这样程序开发中必然会产生许多的代理类
所以我们就会想办法可以通过一个代理类完成全部的代理功能,那么我们就需要用动态代理
在上面的示例中,一个代理只能代理一种类型,而且是在编译器就已经确定被代理的对象。而动态代理是在运行时,通过反射机制实现动态代理,并且能够代理各种类型的对象
在Java中要想实现动态代理机制,需要//动态代理类只能代理接口(不支持抽象类),代理类都需要实现InvocationHandler类,实现invoke方法。该invoke方法就是调用被代理接口的所有方法时需要调用的,该invoke方法返回的值是被代理接口的一个实现类
public class LogHandler implements InvocationHandler {
// 目标对象
private Object targetObject;
//绑定关系,也就是关联到哪个接口(与具体的实现类绑定)的哪些方法将被调用时,执行invoke方法。
public Object newProxyInstance(Object targetObject){
this.targetObject=targetObject;
//该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
//第一个参数指定产生代理对象的类加载器,需要将其指定为和目标对象同一个类加载器
//第二个参数要实现和目标对象一样的接口,所以只需要拿到目标对象的实现接口
//第三个参数表明这些被拦截的方法在被拦截时需要执行哪个InvocationHandler的invoke方法
//根据传入的目标返回一个代理对象
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),this);
}
@Override
//关联的这个实现类的方法被调用时将被执行
/*InvocationHandler接口的方法,proxy表示代理,method表示原对象被调用的方法,args表示方法的参数*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("start-->>");
for(int i=0;i<args.length;i++){
System.out.println(args[i]);
}
Object ret=null;
try{
/*原对象方法调用前处理日志信息*/
System.out.println("satrt-->>");
//调用目标方法
ret=method.invoke(targetObject, args);
/*原对象方法调用后处理日志信息*/
System.out.println("success-->>");
}catch(Exception e){
e.printStackTrace();
System.out.println("error-->>");
throw e;
}
return ret;
}
}
客户端代码如下所示:
public class Client {
public static void main(String[] args){
LogHandler logHandler=new LogHandler();
UserManager userManager=(UserManager)logHandler.newProxyInstance(new UserManagerImpl());
//UserManager userManager=new UserManagerImpl();
userManager.addUser("1111", "张三");
}
}
ok,动态代理的代码就展示到这里,讲解一下动态创建代理对象的类,被代理对象targetObject通过参数传递进来,我们通过targetObject.getClass().getClassLoader()获取ClassLoader对象,然后通过targetObject.getClass().getInterfaces()获取它实现的所有接口,然后将targetObject包装到实现了InvocationHandler接口的LogHandler对象中。通过newProxyInstance函数我们就获得了一个动态代理对象。
区别和联系
静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类,静态代理事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行的社会化才知道。
动态代理是实现JDK里的InvocationHandler接口的invoke方法,但注意的是代理的是接口,也就是你的业务类必须要实现接口,通过Proxy里的newProxyInstance得到代理对象。
还有一种动态代理CGLIB,代理的是类,不需要业务类继承接口,通过派生的子类来实现代理。通过在运行时,动态修改字节码达到修改类的目的。
小编寄语:该博文,小编主要简单的介绍了静态代理和动态代理,从设计模式中的代理模式开始说起,到静态代理和动态代理,静态代理是实实在在存在的,是我们自己用键盘打出来的,在编译期加入,提前就指定好了who来调用who,效率高;动态代理,一个类让事情变得更加简单,可以解决创建多个静态代理的麻烦,避免冗余的代码,无论是静态代理还是动态代理,都各有千秋,在项目中该如何使用,小伙伴可以自己掂量,SSH系列,未完待续......
【SSH系列】静态代理&&动态代理的更多相关文章
- java静态和动态代理原理
一.代理概念 为某个对象提供一个代理,以控制对这个对象的访问. 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代.代理类负责请求的预处理.过滤.将请求分派给委托类 ...
- 静态代理,动态代理,Cglib代理详解
一.静态代理 新建一个接口 定义一个玩家方法: package com."".proxy.staticc; public interface Iplayer { public vo ...
- 8、Spring教程之静态代理/动态代理
为什么要学习代理模式,因为AOP的底层机制就是动态代理! 代理模式: 静态代理 动态代理 学习aop之前 , 我们要先了解一下代理模式! 静态代理 静态代理角色分析 抽象角色 : 一般使用接口或者抽象 ...
- 轻松理解 Java 静态代理/动态代理
目录 什么是代理模式 定义 代理模式的主要角色 优点 缺点 静态代理 动态代理 JDK原生动态代理 例子 分析 小结 CGLIB动态代理 例子 分析 final类型 其他方案 尾声 理解Java动态代 ...
- 老生常谈系列之Aop--CGLIB动态代理的底层实现原理
老生常谈系列之Aop--CGLIB动态代理的底层实现原理 前言 上一篇老生常谈系列之Aop--JDK动态代理的底层实现原理简单讲解了JDK动态代理的实现,动态代理常用实现里面的双子星还有另一位--CG ...
- 老生常谈系列之Aop--JDK动态代理的底层实现原理
老生常谈系列之Aop--JDK动态代理的底层实现原理 前言 在Aop系列里面有两篇文章,分别是老生常谈系列之Aop--Spring Aop原理浅析和老生常谈系列之Aop--Spring Aop源码解析 ...
- 啰里吧嗦式讲解java静态代理动态代理模式
一.为啥写这个 文章写的比较啰嗦,有些东西可以不看,因为想看懂框架, 想了解SSH或者SSM框架的设计原理和设计思路, 又去重新看了一遍反射和注解, 然后看别人的博客说想要看懂框架得先看懂设计模式,于 ...
- 静态代理&动态代理
原文地址:http://blog.csdn.net/partner4java/article/details/7048879 静态AOP和动态AOP. 静态代理: 代理对象与被代理对象必须实现同一个接 ...
- Java 的静态代理 动态代理(JDK和cglib)
转载:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是 ...
随机推荐
- Dev GridControl GridView常用属性
1.隐藏最上面的GroupPanel: gridView1.OptionsView.ShowGroupPanel=false; 2.得到当前选定记录某字段的值: sValue=Table.Rows[g ...
- 字符串的一些常用方法 string
##字符串## 字符串: 由0个或多个字符组成,被成对的英文单引号或双引号包含起来的. 字符编码: 每一个字符在计算机存储的编号. 计算机会保存有一套或几套用于标注编号与字符对应关系的字典.(字符集) ...
- 【温故而知新】HTTP 概述
什么是 HTTP 官方解释是 "因特网的多媒体信使",通俗点说,就是个送信的.电话机出来之前,人与人(有一定距离)之间的沟通基本靠写信,然后由快递员送发.如果把 web 服务器和客 ...
- macOS下python3通过scrapy框架重新生成不得姐网站视频采集过程日志
1.搭建虚拟python3环境(Virtualenvwrapper) 参考http://www.cnblogs.com/it-tsz/p/pyhton.html 2.安装scrapy 前提先安装好pi ...
- 什么是HTTP Referer?
什么是Referer? Referer是 HTTP请求header 的一部分,当浏览器(或者模拟浏览器行为)向web 服务器发送请求的时候,头信息里有包含 Referer.比如我在www.sojson ...
- [Luogu 3901]Difference
Description Input Output Sample Input 4 2 1 2 3 2 1 3 2 4 Sample Output Yes No HINT 题解 莫队.加个标记数组维护该数 ...
- SAC E#1 - 一道中档题 Factorial
题目背景 SOL君(炉石主播)和SOL菌(完美信息教室讲师)是好朋友. 题目描述 SOL君很喜欢阶乘.而SOL菌很喜欢研究进制. 这一天,SOL君跟SOL菌炫技,随口算出了n的阶乘. SOL菌表示不服 ...
- 计蒜客NOIP模拟赛4 D1T1 小X的质数
小 X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感.小 X 认为,质数是一切自然数起源的地方. 在小 X 的认知里,质数是除了本身和 1以外,没有其他因数的数字. 但由于小 X ...
- hdu 5645 DZY Loves Balls
DZY Loves Balls Accepts: 659 Submissions: 1393 Time Limit: 4000/2000 MS (Java/Others) Memory Lim ...
- 例10-10 uva10491(简单概率)
题意: 在a+b扇门,a扇后面是牛,b扇后面是车.在你选择一扇门后,主持人为你打开另外c扇门,然后你再选一扇, 求是车的概率 ①先选牛:a/(a+b),然后还剩a+b-c-1扇门,其中b扇为车,所以a ...