精华内容
下载资源
问答
  • 作者:Intopass ...来源:知乎 著作权归作者所有。商业转载请联系作者获得...① 首先你要明白静态代理作用 我们有一个字体提供类,有多种实现(从磁盘,从网络,从系统) public interface FontProvider { Font...

    作者:Intopass
    链接:https://www.zhihu.com/question/20794107/answer/75164285
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    ① 首先你要明白静态代理的作用
    我们有一个字体提供类,有多种实现(从磁盘,从网络,从系统)

    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());
        }
    }
    

    当然,我们直接修改FontProviderFromDisk类也可以实现目的,但是我们还有FontProviderFromNet, FontProviderFromSystem等多种实现类,一一修改太过繁琐且易出错。
    况且将来还可能添加日志,权限检查,异常处理等功能显然用代理类更好一点。

    ② 然而为什么要用动态代理?
    考虑以下各种情况,有多个提供类,每个类都有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()));
        }
    }
    

    ③ 这也是为什么Spring这么受欢迎的一个原因
    Spring容器代替工厂,Spring AOP代替JDK动态代理,让面向切面编程更容易实现。
    在Spring的帮助下轻松添加,移除动态代理,且对源代码无任何影响。

    展开全文
  • Java 动态代理作用什么

    千次阅读 2016-09-12 12:00:22
    首先你要明白静态代理作用我们有一个字体提供类,有多种实现(从磁盘,从网络,从系统) public interface FontProvider { Font getFont(String name); } public abstract class ProviderFactory { public...

    首先你要明白静态代理的作用我们有一个字体提供类,有多种实现(从磁盘,从网络,从系统)

    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());
    	}
    }

    当然,我们直接修改FontProviderFromDisk类也可以实现目的,但是我们还有FontProviderFromNet, FontProviderFromSystem等多种实现类,一一修改太过繁琐且易出错。
    况且将来还可能添加日志,权限检查,异常处理等功能显然用代理类更好一点。

    ② 然而为什么要用动态代理?
    考虑以下各种情况,有多个提供类,每个类都有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()));
    	}
    }

    ③ 这也是为什么Spring这么受欢迎的一个原因
    Spring容器代替工厂,Spring AOP代替JDK动态代理,让面向切面编程更容易实现。在Spring的帮助下轻松添加,移除动态代理,且对源代码无任何影响。

    展开全文
  • Java 动态代理作用什么 ==AOP?

    千次阅读 2016-12-08 14:38:36
    关于动态代理设计模式很可能题主就在不知不觉中使用了,例如Spring中的AOP,Struts2中的拦截器等。 先来看静态代理模式代码: package test; public interface Subject { public void doSomething(); } ...
     
    
    展开全文
  • 动态代理的好处是什么

    千次阅读 2018-06-09 12:59:48
    静态代理:了解设计模式中的代理模式的童鞋应该都知道如果想要为被代理类生成...动态代理:其实动态代理与静态代理的本质一样,最终程序运行时都需要生成一个代理对象实例,通过它来完成相关增强以及业务逻辑,只...

    静态代理:了解设计模式中的代理模式的童鞋应该都知道,如果想要生成代理类,需要让代理类和被代理类实现同一个接口,并且在代理类中添加被代理类的引用,代理类方法实现中添加代理逻辑,并决定是否调用被代理类方法,这种通过硬编码的方式指定代理类与被代理类的方式,叫静态代理。可以明显看出,静态代理类与被代理类是强耦合的,如果要代理100个类,你就得写100个代理类

    动态代理:其实动态代理与静态代理的本质一样,最终程序运行时都需要生成一个代理对象实例,通过它来完成相关增强以及业务逻辑,只不过静态代理需要硬编码的方式指定,而动态代理则是以动态方式生成代理(有编译时操作字节码生成的方式、运行时通过反射、字节码生成的方式)动态生成的好处很明显代理逻辑与业务逻辑是互相独立的,没有耦合,代理1个类或100个类要做的事情没有任何区别

    说到耦合,必须把AOP拿来说道说道:传统面向对象思想中,如果想要实现功能复用,要么继承、要么引用,无论哪种方式,对代码都有一定的侵入性,耦合无可避免,侵入性啥意思?简单来说:如果你想要用它增强你程序的功能,你必须改动你的程序代码,那它就具有侵入性。如果只有一点两点需要增强还好说,如果大量的功能点需要被增强,工作量就会很大,代码也不太优雅。想象一下,如果你对外公开了一系列的接口,现在领导说了,接口要加权限控制。在哪加?最笨的当然就是写个程序验证的逻辑,然后每个接口都拿来调用一遍。这也正是面向对象思想的短板,在要为程序新增一些通用功能时,只能通过耦合的方式才能进行。AOP正是为此而生,AOP旨在通过一种无耦合的方式来为程序带来增强。而动态代理,就是AOP实现方式中的一种

    我举两个例子,说明下用动态代理实现功能增强,要怎么做,怎么就解耦了,哪里就方便了:

            springAOP大家一定耳熟能详,它借鉴了AOP的思想,通过动态代理实现功能的无耦合增强,企业级应用开发时,当需要为程序添加通用功能时,springAOP应该是你的首选之一,比如现在要给系统对外的一系列接口添加一个权限验证功能,只需要两步即可 

    编写切面类,如下:       

    @Aspect
    @Component
    public class AuthAspect{
         @Around(value="pointCut()") 
              public Object doAround(ProceedingJoinPoint pjp) throws Throwable{ 
                   if(!havePermission()) return "没有权限..."; 
                   return pjp.proceed(pjp.getArgs());
              }
    }
    

    可以看到,代理逻辑是独立的,没有也不需要任何与被代理相关的内容,是为解耦,有了代理逻辑后,我们只要按照spring的规则配置好要代理的范围就好了(也就是代理哪些类的哪些方法),spring会为这些目标类生成动态代理对象,功能增强就是如此简单

             RPC框架大家应该也都接触过,客户端可以像调用本地对象的方法一样调用远程方法,这里的本地对象其实就是个动态代理对象,在rpc中,这类代理对象有个专业的名字,叫做stub(桩),stub对象的创建方式大概是这样的:

    为了方便理解,我将其简化了下,这里使用了jdk自带的代理对象生成方法,Proxy.newProxyInstance,需要在InvocationHandler的invoke方法中实现代理逻辑,在rpc框架中,代理逻辑可以简单理解为连接服务提供端,发送请求,获取返回。有了这个createStub方法,就可以很方便的生成任意我们想要调用的服务的代理对象了,还是非常方便的;这就是解耦的好处..

    总结一下:代理分为静态代理和动态代理,静态代理将代理类和被代理类耦合在一起,实现增强时非常不便,需要大量编码;

    AOP的宗旨是实现无耦合的增强,动态代理就是AOP思想的实现方式之一,无耦合的方式对代码没有侵入性,可以很方便的实现功能增强,如果你需要给你的代码添加一些通用的增强功能,你应该第一时间想到动态代理

     

    PS:如果有不足之处,欢迎指出;如果解决了你的疑惑,就点个赞吧o(* ̄︶ ̄*)o

    展开全文
  • 网上看了好多博客,都说是在代理的方法前后执行一个逻辑,那aop也能实现,为什么还要用到动态代理,这个不明白了。。。
  • Java动态代理作用及好处

    万次阅读 2018-07-15 17:49:02
    Java动态代理的优势是实现无侵入式的代码扩展;也就是方法的增强,让你可以在不用修改源码的情况下,增强一些方法;在方法的前后你可以做你任何想做的事情(甚至不去执行这个方法就可以)。 1.动态代理是设计模式中...
  • 代理IP是什么代理IP有什么作用

    千次阅读 2021-03-05 12:57:07
    代理IP是什么?代理IP有什么作用? 随着互联网的普及与高速发展,互联网工作者对于网络的需求也越来越大...下面就为大家详细介绍什么是IP代理,以及IP代理的用处。 一、代理IP是什么? 代理IP又称代理服务器(Proxy Serv
  • 轻松学,Java 中的代理模式及动态代理

    万次阅读 多人点赞 2017-06-29 22:08:55
    前几天我写了《秒懂,Java 注解 (Annotation)你可以这样学》,因为注解其实算反射技术中的一部分,然后我想了一下,反射技术中还有个常见的概念就是动态代理,于是索性再写一篇关于动态代理的博文好了。...
  • java学习——Java 动态代理机制分析

    千次阅读 2017-04-12 16:53:50
    越学越觉得自己不懂的越多!...https://www.ibm.com/developerworks/cn/java/j-lo-proxy1/Java 动态代理作用什么? https://www.zhihu.com/question/20794107Java动态代理机制详解(JDK 和CGLIB,Javassist,A
  • 关于java动态代理作用,小白理解

    千次阅读 多人点赞 2018-08-24 16:20:07
    关于动态代理这个词,嗯......太高深了,这里先咳嗽两声。 我今天买了两本书,一本英语,一本数学,书可以读,看。 public interface Book { void readTheBook(); } 英语和数学,虽然是书,但内容不一样。 ...
  • 动态代理

    千次阅读 2019-03-23 19:29:52
    动态代理实例: public class ProxyTest { public static void main(String[] args) { //1.创建真实对象 Lenovo lenovo = new Lenovo(); /* 动态代理的注意事项: 1.动态代理对接口有效. 2.动态代理...
  • (1)什么是代理? 代理是一种常用的设计模式,主要作用是为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以再客户端和目标对象之间起到中介的作用. ...
  • 动态代理由浅入深

    2018-09-04 18:45:02
    动态代理作用:可以在不改变原有类的基础上对方法进行增强。执行代理对象的任何方法,就需要执行invocationHandler的invoke方法。本文对以上内容进行了举例分析。
  • 实例理解JDK动态代理和Cglib动态代理及其区别 深入理解设计模式之代理模式 代理商代理化妆品生产理解JDK动态代理 代理商代理汽车制造理解Cglib动态代理
  • Spring AOP的作用动态代理模式

    千次阅读 2019-02-26 17:16:40
    AOP是基于代理模式的。 代理模式: 当我们需要修改一个类,在类中加入代码时,为了不破坏这个类的封装性。可以使用代理模式,建立一个代理类。 比如:修改需求,在调用UserController类的saveUser()方法之前要...
  • JDK动态代理

    千次阅读 2019-12-06 15:47:58
    什么是动态代理呢? JDK的动态代理,就是在程序运行的过程中,根据被代理的接口来动态生成代理类的class文件,并加载运行的过程。只支持接口的代理。 动态代理是通过JDK的Proxy和一个调用处理器InvocationHandler来...
  • 动态代理是 AOP(Aspect Orient Programming)编程思想,理解动态代理原理,对学习AOP框架至关重要。 JDK动态代理不需要任何外部依赖,但是只能基于接口进行代理;CGLIB通过继承的方式进行代理,无论目标对象有没有...
  • 关于JDK动态代理的学习。首先先整明白了大体的思路,一个实现了某些接口的被代理类。一个实现了InvocationHandle的代理类,然后通过Proxy类下的静态方法newProxyInstance进行织入产生一个融合了代理类和被代理类的...
  • 动态代理和静态代理到底有什么区别,好处在哪里?
  • 动态代理及JDK动态代理源码分析

    千次阅读 2014-04-14 23:16:41
    JAVA的动态代理机制可以动态的创建代理并动态的处理代理方法调用,只要简单指定一组接口及为拖累对象,就能动态的获取代理类
  • jdk的动态代理及为什么需要接口

    万次阅读 多人点赞 2017-12-01 14:38:30
    一直不待明白的是为什么,jdk的动态代理需要接口才能实现,这也是其短板和令人诟病的地方。很多的博文说的很复杂,代码一大堆,没有太明白。手打了一下,参考了一些优秀的博文,在这里给自己做个总结。 首先,动态...
  • 静态代理和动态代理

    万次阅读 2019-10-08 11:53:04
    静态代理和动态代理的实现和讲解
  • JDK动态代理什么必须用接口

    千次阅读 2017-08-23 14:00:51
    JDK动态代理什么必须用接口 JDK动态代理与CGLIB动态代理。从Spring的AOP框架介绍中得知对于使用接口的类,Spring使用JDK动态代理,没有接口的就使用别的AOP框架aspectj,但这些都是依赖于Java字节码工具ASM生成一...
  • jdk动态代理的实现原理: 拿到被代理类的引用,并获取所有接口信息(反射获取) jdk proxy.newInstance生成新的类,实现接口方法 动态生成java代码,增强逻辑代码也写入 编译java代码生成class文件 加载并运行...
  • spring 动态代理

    千次阅读 2019-03-15 21:38:59
    动态代理 cglib代理 动态代理 代理模式: 静态代理 动态代理 (Spring如果发现被代理的类有接口的话,就用动态代理,否则用cglib) 动态代理 反射 JAVA的动态代理 代理模式 代理模式是常用的java设计...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 185,951
精华内容 74,380
关键字:

动态代理的作用是什么