代理实现方式

Posted lwdmaib

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代理实现方式相关的知识,希望对你有一定的参考价值。

一、静态代理: 

   静态代理实现  通过代理对象与被代理对象实现同一个接口,被代理对象中实现对代理对象中的方法进行增强  弊端:必须继承或实现同一个接口

    定义一个接口ProposalService

public interface ProposalService {

    public void save();
}

    目标对象(也就是被代理对象)实现ProposalService接口

/**
 * 目标对象
 * @author Administrator
 *
 */
public class ProposalServiceImpl implements ProposalService {
    /**
     * 目标对象要被增强的方法
     */
    @Override
    public void save() {
        // TODO Auto-generated method stub
       System.out.println("当前对象执行的save方法");
    }
}

    代理对象 实现ProposalService接口

/**
 * 代理对象实现类
 * @author Administrator
 *
 */
public class ProxyProposal implements ProposalService{

    private ProposalService target;
    
    public ProxyProposal (ProposalService target){
        this.target=target;
    }
    /**
     * 代理对象实现proposalService接口对象方法增强
     */
    @Override
    public void save() {
        // TODO Auto-generated method stub
        System.out.println("开始事务");
        target.save();
        System.out.println("提交事务");
    }

}

 测试类实现:

public class Test {

    public static void main(String[] args) {
        //目标对象
        ProposalService target = new ProposalServiceImpl();
        //代理对象
        ProxyProposal proxyProposal = new ProxyProposal(target);
        //调用增强的方法
        proxyProposal.save();
    }
}

为了解决代理对象与被代理对象必须实现同一接口的弊端采用动态代理方式。

二、动态代理

     定义一个接口

package cn.ac.bcc.dynamic.proxy.service;
/**
 *  动态代理方式  java api接口
 * @author Administrator
 *
 */
public interface ProposalService {
    
    public void save();

}

定义接口实现类 即要增强的目标对象类

package cn.ac.bcc.dynamic.proxy.service.impl;

import cn.ac.bcc.dynamic.proxy.service.ProposalService;
/**
 * 目标对象  
 * @author Administrator
 *
 */
public class ProposalServiceImpl implements ProposalService {

    /**
     *  目标方法  事项对该方法增强
     */
    @Override
    public void save() {
        // TODO Auto-generated method stub
        System.out.println("我是目标方法");
    }
    
}

代理实例类

package cn.ac.bcc.dynamic.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 *  代理对象工厂类  用来创建代理对象
 * @author Administrator
 *
 */
public class ProxyFactroy {
    //用来接收目标对象
    private Object target;
    
    public ProxyFactroy(Object target){
        this.target=target;
    }
    /**
     *  获取代理对象
     *  newProxyInstance(ClassLoader loader,Interfaces interface,InvocationHandler invocationHandle)
     *  参数一:目标对象类加载器对象  通过加载器获取当前目标全类
     *  参数二:目标对象实现的接口类型  数组  class<>[]
     *  参数三:
     * @return
     */
    public Object getNewInstanceProxy(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            /**
             * invoke(Object proxy, Method method, Object[] args)
             * 参数一:代理实例  并不是目标对象
             * 参数二:目标对象反射类型方法类对象
             * 参数三:目标方法中参数数组
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("对目标方法开始增强代码。。。。");
                //采用反射方式 调用目标方法  返回目标对象
                Object invoke = method.invoke(target, args);
                System.out.println("对目标方法执行完之后增强的代码。。。。");
                return invoke;
            }
        });
    }
}

测试类:

package cn.ac.bcc.dynamic.proxy.test;

import cn.ac.bcc.dynamic.proxy.ProxyFactroy;
import cn.ac.bcc.dynamic.proxy.service.ProposalService;
import cn.ac.bcc.dynamic.proxy.service.impl.ProposalServiceImpl;

/**
 * java api方式实现动态代理测试类
 * @author Administrator
 *
 */
public class DynProxyTest {
    
    public static void main(String[] args) {
        
        //创建目标对象
        ProposalService proposalService= new ProposalServiceImpl();
        
        //创建代理工厂对象传入目标对象获取代理实例
        ProposalService ps = (ProposalService) new ProxyFactroy(proposalService).getNewInstanceProxy();
        //代理对象调用save方法 出发增强方法
        ps.save();
        
    }

}

问题总结:开始在invoke(Object proxy,method method,Object args[])   Object proxy认为是目标对象  在method.invoke(目标对象,args)  以为是invoke传入的参数出现异常

技术分享图片

原因就是invoke(Object proxy)  proxy 并不是目标对象  而是在其上调用方法的代理实例

详解推荐博客地址:https://blog.csdn.net/truong/article/details/34857951

 

以上是关于代理实现方式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式——代理模式

常用的几个JQuery代码片段

Forge Viewer - 如何在场景中访问(或获取渲染/片段代理)克隆的网格?

Java动态代理

Java动态代理

Java动态代理