---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
动态代理学习总结:
1.动态代理是相对于静态代理而言的,有时候我们需要去扩展一个类的功能或去控制程序员对类中方法的访问,但又不想去修改原来的类,而且,有时候我们根本不可能去修改原来的类,因为可能这个类不是我们写的,没有他的源代码,这时候就要用到代理了。
2.代理工作的方式。代理在调用者和被调用者之间构建了一个中间层,所有对被调用者方法的调用都被转发到了代理类上,在代理类上,我们可以做一些事情,比如,决定是否允许对被调用着的访问,或在访问调用者之前或之后做一些其他额外的工作。
3.代理的创建:
1.静态代理的创建:静态代理有两种创建方式,可以继承被代理的类,重写被代理类里对应的方法,也可以通过实现被代理类实现的接口,从新实现对应的方法:
1.通过继承的方式创建代理:
/** * 通过继承的方式实现的代理无需对源代码进行重写, * 代理类是被当作被代理类来使用的,这个方式有个缺点, * 就是和原来的类耦合性太大,每一个被代理的类都要 * 专门写一个 代理类,无法做到代码的重用。而且, * 代理类中的方法签名无法、改变,因为代理类是被当 * 作被代理类使用的,一旦修改方法签名就会调用失败。 */ public class Base{ public void function1(){ System.out.println("我是被代理类中的方法1"); } public void function2(String user){ System.out.println("我是被代理类中的方法2,调用我的用户是:"+user); } } public class Proxy extends Base{ public void function1(){ System.out.println("我是代理类中的方法1,我在这对被代理类中的方法1进行了拦截"); } public void function2(String user){ if("admin".equals(msg.trim())){ System.out.println("我是代理类中的方法2,我在这做了权限判断,只有用户为admin的才允许对被代理类中的方法2进行调用"); Super.function2(user); }else{ System.out.println("对不起,您没有权限调用该方法"); } } }
2.通过 实现接口的方式来创建代理:/** * 通过实现接口创建代理有一个致命的缺陷 * 就是被代理的类必须实现了相应的接口, * 如果没有实现相应的接口,则无法通过这 * 个方式创建代理,通过接口创建代理,降低 * 了代理类和被代理类之间的耦合性,代理类 * 可以为多个实现了相同接口的类服务,而且, *接口隐藏了真正的被代理类的信息,调用者 * 不知道为他服务的究竟是哪个类,这样以后要 * 维护真正的被代理类时就很容易了。 */ public interface BaseInterface{ public void function1(); public void function2(String user); } public class Base implements BaseInterface{ public void function1(){ System.out.println("我实现了BaseInterface接口中的function1方法"); } public void function2(String user){ System.out.println("我实现了BaseInterface接口中的function2方法,当前调用者是:"+user); } } public class Proxy implements BaseInterface{ private Base base=new Base(); public void function1(){ System.out.println("我通过接口实现了对Base类的代理,我在这对他的function1方法进行了拦截"); } public void function2(String user){ if("admin".equals(user.trim())){ System.out.println("我通过接口实现了对Base类的代理,我在这做了权限判断,只有用户为admin的才允许调用Base类的function2方法"); base.function2(user); }else{ System.out.println("对不起,您没有权限调用该方法"); } } }
2.动态代理的创建:创建动态代理要用到 Proxy类和 InvocationHandler接口:/** * 动态代理是基于接口的,其中还用到了反射技术,常被用在 * 框架中,因为是基于接口的,所有与被代理类之间的耦合性 * 降低,而且隐藏了被代理类的具体信息,调用者所知道的一切 * 就只有接口了,因为使用了反射技术,我们调用方法更加灵活 * 不必将调用代码以硬编码的方式写死在原文件了。 */ public interface BaseInterface{ public void function1(); public void function2(String user); } public class Base implements BaseInterface{ public void function1(){ System.out.println("我是Base类中的function1方法") } public void function2(String user){ System.out.println("我是Base类中的function2方法"); } } public class handler implements InvocationHandler{ private Base base=new Base(); public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if("function1".equals(method.getName())){//这里的方法名可以以配置文件的方式动态读取,不必进行硬编码 System.out.println("我是代理类,我对被代理类的方法1进行了拦截"); return null;//如果调用的是方法1则进行拦截 }else if("function2".equals(method.getName())){ if("admin".equals(args[0])){//如果是管理员调用该方法则放行,否则拦截 System.out.println("我是代理类,所有对被代理类的调用都要被转发到我这进行权限判断,当前用户为admin,允许调用"); return method.invoke(base,args);//调用被代理类上对应的方法 }else{ System.out.println("对不起,您没有权限调用该方法"); return null; } } } } public class Test{ public static void main(String[]args){ /** * Proxy类的newProxyInstance方法说明: * newProxyInstance方法返回值是object类型,这是为了通用性, * 因为他是动态代理,被代理的类是动态的无法在写这个方法给出 * 具体返回值,不过貌似可以通过泛型来实现,他有三个参数: * ClassLoader,Interface,Handler,动态代理本质上还是基于接口 * 进行代理的,所有被代理的类必须实现相应的接口,否则无法创建 * 动态代理,Interface参数即为被代理类实现的接口,ClassLoader可为 * 任意的一个ClassLoader,但为了能顺利加载被代理类,推荐使用被代理类 * 上的getClassLoader()方法返回的ClassLoader,因为这个方法返回的ClassLoader * 在当前目录下就能加载被代理的类,用其他ClassLoader可能会出现无法找到 * 被代理类的情况,Handler参数为转发对象,所有对被代理类的调用都被转发到 * 这个类上的invoke方法里,我们可以在这个方法里做一些感兴趣的事。 */ BaseInterface BI= (BaseInterface) Proxy.newProxyInstance( Base.class.getClassLoader(),Base.class.getInterfaces(),new handler()); //测试创建的动态代理类 BI.function1(); BI.function2("admin"); BI.function2("other"); } } 运行结果如下: 我是代理类,我对被代理类的方法1进行了拦截 我是代理类,所有对被代理类的调用都要被转发到我这进行权限判断,当前用户为admin,允许调用 对不起,您没有权限调用该方法
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
详细请查看:www.itheima.com