JAVA 动态代理笔记
- 格式:doc
- 大小:34.00 KB
- 文档页数:3
java设计模式之代理模式实验报告总结与反思摘要:一、代理模式概述二、代理模式应用场景三、代理模式实现1.静态代理2.动态代理四、代理模式优缺点五、实验总结与反思正文:一、代理模式概述代理模式(Proxy Pattern)是Java设计模式中的一种,它通过为其他对象提供一个代理,实现对目标对象的间接引用。
代理模式在实际应用中十分广泛,可以帮助我们解决一些复杂场景下的问题。
二、代理模式应用场景1.远程加载图片:在移动端开发中,我们常常需要先加载一个小图,根据用户意愿再开启线程加载大图。
这里的小图就可以看作是代理。
2.权限控制:在一些系统中,可能有部分用户需要访问某些受保护的功能,而其他用户则不需要。
这时,可以通过代理实现访问控制,仅允许特定用户访问受保护的功能。
三、代理模式实现3.1 静态代理静态代理是通过创建一个代理类来实现目标方法的拦截和增强。
以下是一个简单的静态代理示例:```javapublic interface Subject {void work();}public class RealSubject implements Subject {@Overridepublic void work() {System.out.println("真实对象执行工作");}}public class Proxy implements Subject {private RealSubject realSubject;public Proxy(RealSubject realSubject) {this.realSubject = realSubject;}@Overridepublic void work() {System.out.println("代理对象执行工作");realSubject.work();}}public class Main {public static void main(String[] args) {RealSubject realSubject = new RealSubject();Proxy proxy = new Proxy(realSubject);proxy.work();}}```3.2 动态代理动态代理是通过实现目标类的InvocationHandler 接口来拦截目标方法。
探索JAVA中的动态代理与静态代理在JAVA编程领域,代理模式是一种常见的设计模式,其中动态代理和静态代理是两种常用的代理方式。
本文将深入探讨JAVA中的动态代理与静态代理,揭示它们的特点和应用场景。
静态代理静态代理是在编译时就已经确定的代理方式。
在静态代理中,代理类和委托类在编译期间就已经确定,代理类负责对委托类的方法进行包装和增强。
静态代理的优点是结构简单清晰,易于理解和实现,但缺点是不够灵活,每个需要代理的类都需要一个对应的代理类。
动态代理动态代理是在运行时根据需要动态生成代理类的代理方式。
JAVA中的动态代理主要依靠ng.reflect.Proxy类实现。
动态代理相比静态代理更加灵活,可以减少重复代码,但是实现相对复杂,性能也稍逊于静态代理。
动态代理与静态代理的比较灵活性:动态代理更加灵活,可以动态处理多个委托类的方法调用,而静态代理在编译期就已经确定代理类。
实现复杂度:动态代理的实现相对复杂,需要通过反射机制动态生成代理类,而静态代理则是静态定义代理类。
性能:静态代理在性能上优于动态代理,因为动态代理需要在运行时动态生成代理类,存在一定的性能损耗。
动态代理与静态代理的应用场景静态代理应用场景:当代理类在编译期间就已经确定,并且不需要频繁变更时,静态代理是一个不错的选择。
动态代理应用场景:当需要动态处理多个委托类的方法调用,或者需要减少重复代码时,动态代理更适合使用。
在JAVA编程中,动态代理与静态代理各有优缺点,应根据具体需求和场景选择合适的代理方式。
动态代理更加灵活,适用于需要动态处理多个委托类的方法调用的场景;而静态代理结构清晰,适用于代理类较为固定的情况下。
在JAVA编程中,动态代理和静态代理是两种常见的代理方式,根据具体需求和场景选择合适的代理方式至关重要。
java动态代理
⼀:动态代理:
1.JDK动态代理(接⼝⽅式)
介绍:使⽤java反射包中的类和接⼝实现动态代理的功能,反射包:ng.reflect,⾥⾯有三个类:InvocationHandler,Method,Proxy
(1)InvocationHandler(调⽤处理器) ⾥⾯就⼀个⽅法:invoke()
invoke():表⽰代理类要执⾏的功能代码,代理类要完成的功能就写在invoke()⽅法中
代理类完成的功能:
1.调⽤⽬标⽅法,执⾏⽬标⽅法的功能
2.功能增强,在调⽤⽬标⽅法的时候,增强功能
(2)⽅法原型:
public object invoke(Object proxy,Method method,Object[] args)
参数解析:
Object proxy:jdk创建的代理对象,⽆需赋值
Method method:⽬标类中的⽅法,jdk提供method对象,表⽰⽅法,确切的说是表⽰⽬标类中的⽅法,Method.invoke(⽬标对象,⽅法的参数)
Object[] args:⽬标类中的⽅法参数,jdk提供
(3)怎么⽤?
1.创建⼀个类实现InvocationHandler
2.重写invoke()⽅法
(4)代码实现:
代理类代码拆分解析:
总结:动态代理流程
总结:
2.Cglib代理(第三⽅库,继承⽅式)
解析:第三⽅⼯具库,原理是继承,Cglib通过继承⽬标类,创建它的⼦类,在⼦类中重写⽗类中同名的⽅法,实现功能的修改,在很多框架中都有应⽤,⽐如mybatis和spring中都有使⽤。
Java代理:静态代理与动态代理的不同实现详解及示例
在Java编程中,代理是一种设计模式,它允许一个类代表另一个类执行某些操作。
代理模式在许多场景中都非常有用,例如远程方法调用、数据缓存、访问控制等。
Java中的代理分为静态代理和动态代理两种类型。
本文将对这两种代理进行详细的解释和示例。
一、静态代理
静态代理在编译时就确定了代理类和被代理类的关系。
实现静态代理需要以下几个步骤:
1.定义一个接口,被代理类应该实现这个接口。
2.创建一个实现了上述接口的代理类,并在该类中调用被代理类的相应方法。
3.在客户端代码中使用代理类,而不是直接使用被代理类。
下面是一个简单的示例:
假设有一个接口Animal和一个实现类Dog:
创建一个实现了Animal接口的静态代理类DogProxy:
在客户端代码中使用静态代理:
二、动态代理
动态代理在运行时动态地创建代理类,而不是在编译时就确定。
实现动态代理需要以下几个步骤:
1.创建一个接口,被代理类应该实现这个接口。
2.创建一个实现了上述接口的被代理类。
3.创建一个实现了上述接口的动态代理类,并在该类中调用被代理类的相应
方法。
动态代理类通常使用Java反射机制来调用被代理类的相应方法。
4.在客户端代码中使用动态代理类。
Spring⽇常笔记记录10--动态代理实现InvocationHandler动态代理动态代理是指,程序在整个运⾏构成中根本就不存在⽬标类的代理类,⽬标对象的代理对象只是由代理⽣成⼯具(不是真实定义的类)在程序运⾏时由JVM根据反射等机制动态⽣成的。
代理对象与⽬标对象的代理关系在程序运⾏时才确⽴。
⼀、JDK动态代理动态代理的实现⽅式常⽤的有两种:使⽤JDK的Proxy,与通过CGLIB⽣成代理。
jdk的动态要求⽬标对象必须实现接⼝,这是Java设计上的要求。
从jdk1.3以来,Java语⾔通过ng.reflect包提供三个⽀持代理模式Proxy,Method和InvocationHandler。
⼆、CGLIB动态代理第三⽅的⼯具库,创建代理对象,原理是继承。
通过继承⽬标类,创建⼦类。
⼦类就是代理对象,要求⽬标类不能是final的,⽅法也不能是final的三、JDK动态代理底层实现反射包 ng.reflect , ⾥⾯有三个类: InvocationHandler , Method, Proxy.1)InvocationHandler 接⼝(调⽤处理器):就⼀个⽅法invoke()invoke():表⽰代理对象要执⾏的功能代码。
你的代理类要完成的功能就写在invoke()⽅法中。
代理类完成的功能:1. 调⽤⽬标⽅法,执⾏⽬标⽅法的功能2. 功能增强,在⽬标⽅法调⽤时,增加功能。
2)⽅法原型:参数: Object proxy:jdk创建的代理对象,⽆需赋值。
Method method:⽬标类中的⽅法,jdk提供method对象的Object[] args:⽬标类中⽅法的参数, jdk提供的。
public Object invoke(Object proxy, Method method, Object[] args)1) InvocationHandler 接⼝:表⽰你的代理要⼲什么怎么⽤: 1.创建类实现接⼝InvocationHandler2.重写invoke()⽅法,把原来静态代理中代理类要完成的功能,写在这。
《Java基础知识》Java动态代理(InvocationHandler)详解1. 什么是动态代理对象的执⾏⽅法,交给代理来负责。
⽐如user.get() ⽅法,是User对象亲⾃去执⾏。
⽽使⽤代理则是由proxy去执⾏get⽅法。
举例:投资商找明星拍⼴告,投资商是通过经纪⼈联系的,经纪⼈可以帮明星接这个⼴告,也可以拒绝。
做不做,怎么做都叫给经纪⼈和投资商谈。
2. 实际场景应⽤2.1 校验⽤户权限,每⼀个菜单请求,都要判断⼀下请求的⽤户是否有该菜单权限。
菜单多了,代码冗余,且容易遗漏。
通过动态代理就可以实现为:每⼀个⽤户,每⼀个菜单的请求,都经过代理(proxy),由他判断是否有权限,调⽤者只需要调⽤,实现⾃⼰的逻辑,不关⼼权限问题。
3. 动态代理完整案例:/*** 创建⽤户接⼝*/public interface UserBean {String getUser();}import erBean;public class UserBeanImpl implements UserBean {private String user = null;//flag:0 ⽆权限,1有权限。
private String flag = null;public String getFlag() {return flag;}public void setFlag(String flag) {this.flag = flag;}public UserBeanImpl(String user,String flag){er = user;this.flag = flag;}public String getUserName(){return user;}public String getUser(){System.out.println("this is getUser() method!");return user;}public void setUser(String user){er = user;System.out.println("this is setUser() method!");}}import ng.reflect.InvocationHandler;import ng.reflect.Method;public class UserBeanProxy implements InvocationHandler {private Object targetObject;public UserBeanProxy(Object targetObject){this.targetObject = targetObject;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {UserBeanImpl userBean = (UserBeanImpl) targetObject;String flag = userBean.getFlag();Object result = null;//权限判断if("1".equals(flag) ){result = method.invoke(targetObject, args);}else{System.out.println("sorry , You don't have permission");}return result;}}import erBean;import ng.reflect.Proxy;public class TestSection {public static void main(String[] args) {UserBeanImpl targetObject = new UserBeanImpl("蕾蕾","1");UserBeanProxy proxy = new UserBeanProxy(targetObject);//⽣成代理对象UserBean object = (UserBean) Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), proxy);String userName = object.getUser();System.out.println("userName: " + userName);}}运⾏结果:代理代理核⼼代码UserBean object = (UserBean) Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(), proxy);public interface InvocationHandler {public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;}接⼝:InvocationHandler,代理需要实现该接⼝,并且实现⽅法:invoke。
代理-动态代理(jdk自带)前一篇代理-概念与代理模式(静态)讲了代理的概念及代理模式,这一篇讲java中动态代理。
讲之前先来科普一下(网上普遍认可的定义):静态代理:由程序员创建或工具生成代理类的源码,再编译代理类。
所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
动态代理:动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。
代理类和委托类的关系是在程序运行时确定。
又懵逼了吧,大白话讲,静态代理就是代理类(C同学)跟委托类(A同学)间的关系是固定的,程序运行前,代理类跟委托类已经以.class文件形式存在硬盘里。
而动态代理则是,根据需求,决定是否需要创建代理类,需要时,在jvm内存中动态拼接出一份.class文件,而这个.class文件就是代理类,仅存在内存中,程序结束后便销毁。
还是用回上篇的例子:A同学喜欢B同学,想送花,送小礼物给她,但是太过于羞涩,让C同学代替送了。
之后,每逢年过节,鲜花,礼物什么的C同学很乐意代劳,最后的最后,B 同学跟C同学可耻的在一起了。
A同学负责送花,送礼物,B同学负责收花,收礼物,C同学是第三方,仅起到中间媒介的作用。
换成动态代理实现(JDK自带的):思路:1、创建送礼物,送花代理动作接口2、创建真实对象(委托类),实现代理动作接口3、实现InvocationHandler接口,重写invoke方法,自定义代理方法处理策略4、通过Proxy.newProxyInstance方法获取代理对象5、代理对象执行方法总结:静态代理优点:具有代理共有的优点,相对动态代理,静态代理逻辑简单,操作方便。
缺点:1、业务类(委托方)与代理类需要共同实现一个接口,每个方法独立代理,如果业务类拥有较多方法时,代理也随之增加,不如动态代理统一在invoke方法中处理。
(可以对GivingInvocationHandler进行通用化改造)2、业务类(委托方)添加方法或其他操作之后,代理类也必须对应添加,代码维护相当麻烦。
java技术深入研究之动态代理动态代理是相对静态代理而说的,比较废话一句。
其核心就是Proxy.newProxyInstance生产代理类,同时指定这个代理实例的回调接口ng.reflect.InvocationHandler。
先上代码,再做分析:1/**2 * User服务接口类3*/4interface UserService{5/**6 * 添加一个用户7 * @return8*/9public boolean add(String name);10 }1/**2 * User服务接口实现类3*/4class UserServiceImpl implements UserService{56 @Override7public boolean add(String name) {8 System.out.println(String.format("添加一个名为:%s的用户", name));9return true;10 }11 }1/**2 * 代理工具类,用其他类提供代理3*/4class DynamicProxyUtil implements InvocationHandler{5/**6 * 被代理的对象7*/8private Object proxyObject;9/**10 * 将被代理对象传入,以便生产代理类11 * @param proxyObject12 * @return13*/14public Object generateProxyClass(Object proxyObject){15this.proxyObject=proxyObject;//将被代理对象引入该类16//根据被代理对象的类信息生产代理类17 Class<?> clazz = proxyObject.getClass();18/*Proxy.newProxyInstanc方法实现原理:jvm会根据传入的接口及其实现类动态生成如:$Proxy.class字节码类,默认只在内存中,可使用19System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGener atedFiles", "true")将类文件保存在本地磁盘20 $Proxy0 实现要代理的对象接口及其托管对被代理对象所有方法调用21 public final class $Proxy0 extends ng.reflect.Proxy implements UserService22*/23return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);24 }25 @Override26public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {27 System.out.println(String.format("方法%s调用前,传入参数%s", method.getName(),Arrays.toString(args)));28 Object result = method.invoke(this.proxyObject, args);29 System.out.println(String.format("方法%s调用前,返回值%s", method.getName(),result));30return result;31 }3233 }1/**2 * 测试类3*/4public class ClientTest {5public static void main(String[] args) {67 UserService userService = new UserServiceImpl();8//用代理工具类生成一个UserService服务代理9System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGener atedFiles", "true");10 DynamicProxyUtil dynamicProxy = new DynamicProxyUtil();11 UserService userServiceProxy =(UserService)dynamicProxy.generateProxyClass(userService);12//通过生成的代理类来调用方法,而不是直接调用userService.add。
【原创】Java动态代理总结
Proxy类的静态⽅法newProxyInstance( loader, <?>[] interfaces, h) 创建代理对象。
该⽅法的三个参数解释如下:
1. loader:指定被代理类的ClassLoader。
2. interfaces:指定被代理类所实现的接⼝。
注意,该参数是⼀个Class类型的数组,所以⽀持多个接⼝。
当interfaces中指定的任意接⼝的⽅法被调⽤时,调⽤将被拦截,然后转到第三个参数h的invoke⽅法中,执⾏相应的逻辑。
3. h:指定⼀个InvocationHandler的实例。
当第⼆个参数interfaces中指定的任意接⼝的⽅法被调⽤时,程序流程将转到此参数的invoke⽅法,执⾏相应的逻辑。
⽣成的代理对象的真实类型为Proxy,但是实现了被代理类所实现的所有接⼝(其实应该是newInstance⽅法中第⼆个参数interfaces所指定的接⼝,不过⼤部分情况下该参数都被直接指定为被代理类实现的所有接⼝),所以可以通过强制转换,来调⽤被代理类实现的所有接⼝中的所有⽅法。
具体程序实例参见DynamicProxyTestDemo项⽬。
Java动态代理的总结 最近和⼀个好友在聊起Mybatis时,他问⽤Mybatis我们只是配置好mapper,然后写dao层接⼝就实现了dao层⽅法。
然后我说我觉得⽤动态代理可以实现。
然后他⼜说感觉动态代理和外观模式没什么区别,我说:⽤动态代理模式时你想在⼀些代理服务器如Magent(给memcached)提供代理服务时,你调⽤memcached的接⼝和Magent,在如你⽤Nginx做代理服务器时,访问Ngix的http的url并没有因为⽤了代理服务器就发⽣变化,所以我说代理模式和外观有⼀个很明显区别是代理模式接⼝和需要代理的服务接⼝⼀样⽽且代理模式并不做处理,处理还是需要代理的服务,例如在⽤Magent他只是做了⼀些服务器备份,以及路由,负载均衡的处理,⽽实际的命令还是交给memcached来执⾏。
进天闲暇时间就来总结⼀下代理模式,以及jdk,cglib代理模式⽤法,来理解代理模式。
⼀. JAVA的动态代理(⽐较官⽅说法) 代理模式 代理模式是常⽤的java设计模式,他的特征是代理类与委托类有同样的接⼝,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。
代理类与委托类之间通常会存在关联关系,⼀个代理类的对象与⼀个委托类的对象关联,代理类的对象本⾝并不真正实现服务,⽽是通过调⽤委托类的对象的相关⽅法,来提 供特定的服务。
按照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定⼯具⾃动⽣成源代码,再对其编译。
在程序运⾏前,代理类的.class⽂件就已经存在了。
动态代理:在程序运⾏时,运⽤反射机制动态创建⽽成。
⼆. 动态代理实现 ng.reflect.Proxy, Proxy 提供⽤于创建动态代理类和实例的静态⽅法. newProxyInstance() 返回⼀个指定接⼝的代理类实例,该接⼝可以将⽅法调⽤指派到指定的调⽤处理程序。
2.1. Dao接⼝(提供模拟数据访问层接⼝)package javaproxy;/** @author:maybo** @time:2016/2/16** 定义⼀个数据访问层接⼝*/public interface Dao {//模拟数据保存public void save();}2.2. DaoImpl类实现类package javaproxy;public class DaoImpl implements Dao{@Overridepublic void save() {System.out.println("执⾏⼀个保存⽅法。
动态代理笔记
例子:
public interface UserDAO {
public void saveUser();
public void findUsers();
public void removeUser();
}
public class UserDAOImpl implements UserDAO {
public void saveUser() {
System.out.println("=========>save user");
}
public void findUsers() {
System.out.println("=========>find users");
}
public void removeUser() {
System.out.println("=========>remove user");
}
}
如果需要对saveUser方法加上一些事务处理的话,有两种方法可以实现
1 静态代理方法
但是这种方法有个缺点,就是需要依依实现所有的接口中的方法,虽然只是简单的委托,但是也很头痛。
增加一个Proxy类
public class UserDAOProxy implements UserDAO {
private UserDAO dao;
public UserDAOProxy(UserDAO dao){
this.dao=dao;
}
public void saveUser() {
System.out.println("begin transaction");
dao.saveUser();
System.out.println("end transaction");
}
public void findUsers() {
dao.findUsers();
}
public void removeUser() {
dao.removeUser();
}
}
客户类代码:
public class Client {
public static void main(String[] args) {
UserDAO userDAO=new UserDAOImpl();
UserDAO userProxy=new UserDAOProxy(userDAO);
userProxy.saveUser();
userProxy.findUsers();
userProxy.removeUser();
}
}
2 利用动态代理实现。
利用反射机制,截获saveUser方法。
public class TxHandler implements InvocationHandler {
private Object originalObject = null;
public Object bind(Object obj) {
this.originalObject = obj;
//动态构造代理类实例返回,该代理类的方法被调用时,会自动触发invoke方法
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
if(method.getName().equals("saveUser")){
System.out.println("==begin transaction ==");
result=method.invoke(originalObject,args);
System.out.println("==end transaction ==");
} else{
result=method.invoke(originalObject,args);
}
return result;
}
}
客户类代码:
public class Client {
public static void main(String[] args) {
TxHandler tx=new TxHandler();
UserDAO userDAO= new UserDAOImpl();
UserDAO userProxy=(UserDAO)tx.bind(userDAO);
userProxy.saveUser();
userProxy.findUsers();
userProxy.removeUser();
}
}。