Spring原理之代理与动态代理模式总结(四)
来源:互联网 发布:杨千嬅 知乎 编辑:程序博客网 时间:2024/06/05 03:34
代理模式
1,什么是代理模式?
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。2,代理模式有什么好处?
在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。3,代理模式一般涉及到的角色有:
- 抽象角色:声明真实对象和代理对象的共同接口,这样一来在任何可以使用目标对象的地方都可以使用代理对象。
- 代理角色:代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象;代理对象提供一个与目标对象相同的接口,以便可以在任何时候替代目标对象。代理对象通常在客户端调用传递给目标对象之前或之后,执行某个操作,而不是单纯地将调用传递给目标对象,同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
- 真实角色:定义了代理对象所代表的目标对象,代理角色所代表的真实对象,是我们最终要引用的对象,定义了代理对象所代表的目标对象。
public abstract class AbstractObject { //操作 public abstract void operation();}public class RealObject extends AbstractObject { @Override public void operation() { //一些操作 System.out.println("一些操作"); }}public class ProxyObject extends AbstractObject{ RealObject realObject = new RealObject(); @Override public void operation() { //调用目标对象之前可以做相关操作 System.out.println("before"); realObject.operation(); //调用目标对象之后可以做相关操作 System.out.println("after"); }}public class Client { public static void main(String[] args) { // TODO Auto-generated method stub AbstractObject obj = new ProxyObject(); obj.operation(); }}
- 案例二
public interface FontProvider { Font getFont(String name);}public abstract class ProviderFactory { public static FontProvider getFontProvider() { return new FontProviderFromDisk(); }}public class Main() { public static void main(String[] args) { FontProvider fontProvider = ProviderFactory.getFontProvider(); Font font = fontProvider.getFont("微软雅黑"); ...... }}//现在我们希望给他加上一个缓存功能,我们可以用静态代理来完成public class CachedFontProvider implements FontProvider { private FontProvider fontProvider; private Map<String, Font> cached; public CachedFontProvider(FontProvider fontProvider) { this.fontProvider = fontProvider; } public Font getFont(String name) { Font font = cached.get(name); if (font == null) { font = fontProvider.getFont(name); cached.put(name, font); } return font; }}/* 对工厂类进行相应修改,代码使用处不必进行任何修改。 这也是面向接口编程以及工厂模式的一个好处 */public abstract class ProviderFactory { public static FontProvider getFontProvider() { return new CachedFontProvider(new FontProviderFromDisk()); }}
- 案例三
考虑以下各种情况,有多个提供类,每个类都有getXxx(String name)方法,每个类都要加入缓存功能,使用静态代理虽然也能实现,但是也是略显繁琐,需要手动一一创建代理类。public abstract class ProviderFactory { public static FontProvider getFontProvider() {...} public static ImageProvider getImageProvider() {...} public static MusicProvider getMusicProvider() {...} ......}使用动态代理怎么完成呢?public class CachedProviderHandler implements InvocationHandler { private Map<String, Object> cached = new HashMap<>(); private Object target; public CachedProviderHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Type[] types = method.getParameterTypes(); if (method.getName().matches("get.+") && (types.length == 1) && (types[0] == String.class)) { String key = (String) args[0]; Object value = cached.get(key); if (value == null) { value = method.invoke(target, args); cached.put(key, value); } return value; } return method.invoke(target, args); }}public abstract class ProviderFactory { public static FontProvider getFontProvider() { Class<FontProvider> targetClass = FontProvider.class; return (FontProvider) Proxy.newProxyInstance(targetClass.getClassLoader(), new Class[] { targetClass }, new CachedProviderHandler(new FontProviderFromDisk())); }}
动态代理
- 代理:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象。
- 举例:春季回家买票让人代买
动态代理:在程序运行过程中产生的这个对象,此对象其实就是我们刚才反射讲解的内容,所以动态代理其实就是通过反射来生成一个代理。
在Java中
java.lang.reflect
包下提供了一个Proxy类
和一个InvocationHandler接口
,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口
做代理。我们有更强大的代理cglib
。Proxy类中的方法创建动态代理类对象
- public static Object newProxyInstance(ClassLoader loader,Class
public class MyInvocationHandler implements InvocationHandler { private Object target; // 目标对象 public MyInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("权限校验"); Object result = method.invoke(target, args); System.out.println("日志记录"); return result; // 返回的是代理对象 }}public interface StudentDao { public abstract void login(); public abstract void regist();}public class StudentDaoImpl implements StudentDao { @Override public void login() { System.out.println("登录功能"); } @Override public void regist() { System.out.println("注册功能"); }}/* * 用户操作接口 */public interface UserDao { public abstract void add(); public abstract void delete(); public abstract void update(); public abstract void find();}public class UserDaoImpl implements UserDao { @Override public void add() { System.out.println("添加功能"); } @Override public void delete() { System.out.println("删除功能"); } @Override public void update() { System.out.println("修改功能"); } @Override public void find() { System.out.println("查找功能"); }}public class Test { public static void main(String[] args) { UserDao ud = new UserDaoImpl(); ud.add(); ud.delete(); ud.update(); ud.find(); System.out.println("-----------"); // 我们要创建一个动态代理对象 // 我准备对ud对象做一个代理对象 MyInvocationHandler handler = new MyInvocationHandler(ud); UserDao proxy = (UserDao) Proxy.newProxyInstance(ud.getClass() .getClassLoader(), ud.getClass().getInterfaces(), handler); proxy.add(); proxy.delete(); proxy.update(); proxy.find(); System.out.println("-----------"); StudentDao sd = new StudentDaoImpl(); MyInvocationHandler handler2 = new MyInvocationHandler(sd); StudentDao proxy2 = (StudentDao) Proxy.newProxyInstance(sd.getClass() .getClassLoader(), sd.getClass().getInterfaces(), handler2); proxy2.login(); proxy2.regist(); }}
阅读全文
0 0
- Spring原理之代理与动态代理模式总结(四)
- 代理模式之强制代理模式以及动态代理原理
- 《Java与模式》之 代理模式(jdk动态代理)
- java代理模式之静态代理与动态代理
- 代理设计模式之静态代理与动态代理
- 代理设计模式之静态代理与动态代理
- 代理模式之静态代理与动态代理
- Java设计模式(四)之动态代理模式
- Spring的代理模式(静态代理和动态代理)
- Spring的代理模式(静态代理和动态代理)
- spring 动态代理 原理
- Spring之代理设计模式原理与代码展示
- Spring 动态代理(四)- 动态代理核心类
- Spring AOP之动态代理原理解析
- Spring AOP之动态代理原理解析
- 代理模式与动态代理
- 代理模式与动态代理
- 代理模式与动态代理
- jdk的重装
- Codeforces Round #384 (Div. 2) E. Vladik and cards
- TCP和UDP
- [数据库事务与锁]详解二: 数据库的读现象浅析
- CoreData创建托管对象子类后 编译文件重复错误
- Spring原理之代理与动态代理模式总结(四)
- SpringBoot中使用数据缓存
- Android动画笔记
- Flip Game
- centos 6 将python 2.6 升级到python 2.7
- 推荐MongoDB教程
- js中对于DOM1的扩展
- 视图抖动
- 【代码】N个非定长升序数组 合并成一个升序数组