• 动态代理


    1.代理模式

    代理模式作用:

    屏蔽真实行为的访问,让程序更加安全。
    可以对真实行为的调用进行控制。

    通过一个案例:来说明代理的实现以及代理的作用

    代理类和被代理类实现的同一个接口

    1. package cn.itcast.proxy;
    2. //风流的女人
    3. publicinterfaceKindWoman{
    4. publicvoid throwEye();
    5. publicvoid doSomething();
    6. }

    pjl作为被代理类,实现接口

    1. //潘金莲 ---被代理
    2. publicclassPjlimplementsKindWoman{
    3. publicvoid throwEye(){
    4. System.out.println("潘金莲抛媚眼");
    5. }
    6. publicvoid doSomething(){
    7. System.out.println("潘金莲。。。。。。。。");
    8. }
    9. }

    而代理类需要实现接口,同时有一个构造方法,来接受被代理类的对象

    1. //代理
    2. publicclassWpimplementsKindWoman{
    3. privateKindWoman woman;
    4. publicWp(KindWoman woman){
    5. this.woman = woman;
    6. }
    7. publicvoid throwEye(){
    8. //在这里做操作,可以控制是否调用真实行为。
    9. woman.throwEye();
    10. //在这个位置,可以在真实行为调用完成后,在做操作。
    11. }
    12. publicvoid doSomething(){
    13. woman.doSomething();
    14. }
    15. }

    测试的时候,我们执行的是wp,但是调用的是pjl

    1. publicclassXmq{
    2. publicstaticvoid main(String[] args){
    3. KindWoman woman =newJs();
    4. Wp wp =newWp(woman);
    5. wp.throwEye();//真实执行的是潘金莲,但是我们看不到,所以屏蔽了真实行为。
    6. }
    7. }

    代理模式实现:

    1.代理类与被代理类要实现同一个接口.
    2.在代理类中持有被代理对象.
    3.在代理类中调用被代理的行为。

    AOP:面向方面的编程。
    AOP的底层实现就是通过动态代理来做到的。

    2.动态代理

    它就是在代理模式基础上发展的,它不在是对单一的类型进行代理,
    而是可以对任意的一个实现了接口的类的对象做代理。

    3.动态代理实现

    有两种方式:

    1.通过jdk中提供的Proxy类来实现
    这种方式要求,被代理类必须实现接口。
    简单说,只能为接口做代理.
    2.通过cglib来实现。
    它不要求,实现接口。主要是通过修改字节码实现的。

    4 Proxy代码实现:

    Proxy类中有一个方法newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h);

    参数:
    (1)loader:
    要求,传递的是被代理类的类加载器ClassLoader.

    类加载器怎样获取:
    得到其Class对象。在Class类中提供一个方法 getClassLoader();

    (2)interfaces:
    要求:得到被代理对象所实现的接口的所有Class对象。
    怎样获取所有实现接口的Class对象?
    得到其Class对象,在Class类中提供一个方法 getInterfaces();
    它返回的是Class[],就代表所实现接口的所有Class对象。

    (3)h:
    它的类型是InvocationHandler,这是一个接口。
    InvocationHandler 是代理实例的调用处理程序 实现的接口。

    InvocationHandler接口中有一个方法invoke;
    // 参数 proxy就是代理对象
    // 参数method就是调用方法
    // 参数args就是调用的方法的参数
    // 返回值,就是真实行为执行后返回的结果,会传递给代理对象调用的方法.
    public Object invoke(Object proxy, Method method, Object[] args);

    代码

    注意下面代码Proxy.newProxyInstance返回的对象类型应该是接口,此时要注意代理和被代理对象之间是一个兄弟的关系,也就是说他们的父辈是接口,所以一个兄弟不能等于另一个兄弟,而应该等于它的接口,是接口产生的它,而如何去代理你的兄弟呢,在newProxyInstance参数中有需要传递被代理对象的类加载器,还有接口等,这些其实都是说明这个代理类是在那个接口下实现的类,也就是说明他是接口的儿子(被代理类的兄弟),接着要说明我代理哪一个兄弟,需要在InvocationHandler(接口)这个实现类中去说明。
    InvocationHandler这是一个接口,我们才用匿名内部类(用的时候直接穿件了他的对象),他里面有三个参数,第一个就说明了我们需要去代理哪一个兄弟,剩下的 是代理哪一个方法和方法中的参数,具体返回时method.invoke,需要两个参数第一个是具体哪个兄弟。


    我们分析一下到底是怎么代理的,当sproxy.say执行的时候,会实例化InvocationHandler对象,并且执行其中的invoke方法,那么此时第二个参数method就是调用的方法say,第三个参数args就是“james",然后会返回被代理对象执行该方法的结果,得到message,所以代理对象执行的时候是要走invoke方法内的东西,这也就实现了过滤和安全性考虑。上面相同颜色代表同一个东西

    1. publicstaticvoid main(String[] args){
    2. finalKindWoman woman =newPjl();
    3. // 做一个Pjl的代理.
    4. KindWoman proxy =(KindWoman)Proxy.newProxyInstance(woman.getClass()
    5. .getClassLoader(), woman.getClass().getInterfaces(),
    6. newInvocationHandler(){
    7. publicObject invoke(Object proxy,Method method,
    8. Object[] args)throwsThrowable{
    9. return method.invoke(woman, args);//woman.方法名(参数)
    10. }
    11. });
    12. }





  • 相关阅读:
    mysql修改时区time_zone
    magento的布局(layouts)、模块(block)、模板(templates)
    唯品会消息网关的架构定位
    Java应用一般架构
    maven打包命令
    端口查看与封杀
    java程序优化
    高并发下竞争的资源
    java中的多线程高并发与负载均衡的用途
    Web负载均衡的几种实现方式
  • 原文地址:https://www.cnblogs.com/oneNightStand/p/6509812.html
Copyright © 2020-2023  润新知