什么是动态代理啊?哪位大侠能给解答一下啊,并给个实例看看,谢谢啦

解决方案 »

  1.   

    动态代理是 java.lang.reflect 包的一部分,它允许程序创建 代理对象,代理对象能实现一个或多个已知接口,并用反射代替内置的虚方法分派,编程地分派对接口方法的调用。这个过程允许实现“截取”方法调用,重新路由它们或者动态地添加功能。
      

  2.   

    public class SetProxyFactory {
        public static Set getSetProxy(final Set s) {
            return (Set) Proxy.newProxyInstance
              (s.getClass().getClassLoader(),
                    new Class[] { Set.class },
                    new InvocationHandler() {
                        public Object invoke(Object proxy, Method method, 
                          Object[] args) throws Throwable {
                            return method.invoke(s, args);
                        }
                    });
        }
    }
      

  3.   

    网上介绍的更加详细,可以google细看
      

  4.   

    主要是我不太懂,google上是很多,但是为什么我看不懂啊,我是初学者,谁能帮帮忙解释一下,动态代理是用来干什么的
      

  5.   

    主要是把使用的方法给他加一些功能。
    比如:Ibm买电脑,代理商就可以也买电脑还送鼠标。
    IBM.买电脑(){
       买电脑操作();
    }代理商.买电脑(){
       送鼠标操作();
        IBM.买电脑();
    }spring 的事务有用这个,LZ可以去学习下
      

  6.   

    美河有个视频.介绍动太代理的.
    你可以GOOGLE一下.
      

  7.   


    //假设做一个ArrayList 的 添加提示的功能。 就是 在调用它的add方法的时候 输出一句 请检查类型.import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.*;
    import java.util.*;
    class ArrayListProxy implements  InvocationHandler...{
        Object list ;
        
        ArrayListProxy(Object list )...{
            this.list  = list;
        }
        
        
        public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable...{
            
            if(method.getName().equals("add"))...{
                //对特定方法代理
                System.out.println ("请检查类型.......befor:"+method.getName());
            }
            
            //对所有方法代理
            //System.out.println ("请检查类型.......befor:"+method.getName());
            Object o =  method.invoke(list,args);
            
            return o ;
            
        }
        
        
        public static Object factory(Object o )...{
            Class c = o.getClass();
            
            //用真实的对象来构造代理对象
            return Proxy.newProxyInstance(c.getClassLoader(),c.getInterfaces(),new ArrayListProxy(o));
        }
    }class TestDProxy...{
        public static void main(String[] args)...{
            ArrayList al = new ArrayList();
            List pro =  (List)ArrayListProxy.factory(al);
            
            
            pro.add("aaa");
            System.out.println (pro.size());
            
            
            
        }
    }
    更多关于代理 : http://blog.csdn.net/caoyinghui1986/archive/2008/05/16/2450221.aspx
      

  8.   

    动态代理就是可以任意的控制任意对象的执行过程,意思就是说这个对象的执行过程可以由客户端灵活的指定,可能这样说还是不太明确,看下面的例子:
    假如有一个用户的实体类叫User
    package org.chinasoft.proxy.test;/**
     * 用户实体类
     * @author lilei
     *
     */
    public class User {
    private String id;

    public User(String id) {
    this.id = id;
    } public String getId() {
    return id;
    } public void setId(String id) {
    this.id = id;
    }}
    实现对实体类User类的数据管理,UserDAO
    package org.chinasoft.proxy.test;public interface UserDAO {
    //可以有很多的方法(del,update,query...)
    void addUser(User user);}
    不同UserDAO的实现:UserDAOMySQLImpl,UserDAOOracleImplpackage org.chinasoft.proxy.test;public class UserDAOMySQLImpl implements UserDAO {

    public void addUser(User user) {
    // connect to MySQL,insert a row recoder
    System.out.println("connect to MySQL DataBase...");
    System.out.println("id=" + user.getId() +  "的用户信息成功添加到数据库表中...");
    }}
    UserDAOOracleImpl:package org.chinasoft.proxy.test;public class UserDAOOracleImpl implements UserDAO { public void addUser(User user) {
    //connect to Oracle,insert a row recoder
    System.out.println("connect to Oracle DataBase...");
    System.out.println("id=" + user.getId() +  "的用户信息成功添加到数据库表中...");
    }}
    现在假如说,有这样一个需求,就是说想在把用户添加到数据库调用addUser方法之前和之后记录下当前操作的
    的日志(比如某某用户被添加到数据库等等)LogHandler类,功能是负责控制任意被代理对象中任意方法的执行过程,简单说具体到本类中功能就是记录方法
    运行前后的日志
    package org.chinasoft.proxy.test;import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;public class LogHandler implements InvocationHandler {
    //持有被代理对象的引用(此引用可以有外部灵活制定的)
    private Object target;

    public LogHandler(Object target) {
    this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("开始记录日志,添加用户方法开始执行...");
    method.invoke(target, args);
    System.out.println("开始记录日志,添加用户方法执行结束...");
    return null;
    }}
    测试类:TestProxypackage org.chinasoft.proxy.test;import java.lang.reflect.Proxy;public class TestProxy {

    public static void main(String[] args) {
    UserDAO daoImpl  = new UserDAOMySQLImpl();
    //拿到实现被代理类(UserDAO)的实现类的对象
    UserDAO dao = (UserDAO)getInstance(daoImpl);

    User user = new User("001");
    dao.addUser(user);
    } /**
     * 
     * @param dao 被代理的对象
     * @return 返回的是实现了被代理对象的对象(JDK $Proxy0)
     */
    public static Object getInstance(UserDAO dao) {
    Object o = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), 
    new Class[]{UserDAO.class}, 
    new LogHandler(dao));
    return o;
    }

    }
    程序运行结果:开始记录日志,添加用户方法开始执行...
    connect to MySQL DataBase...
    id=001的用户信息成功添加到数据库表中...
    开始记录日志,添加用户方法执行结束...
    假如现在还有一个需求,想记录下在添加用户成功之后,记录添加用户方法的运行时间
    使用代理之后,就可以不用改变原来的代码,直接扩展一个记录时间的方法处理器就可以了,比如说叫
    TimeHandler,是不是更加灵活了假如说现在还有一个需求,想在方法执行的前后加上权限的检查,同样可以直接扩展出一个SecureHandler来处理方法调用。假如说还有这样一个需求:想在方法中加上Transaction(事物)的控制,是不是只需要一个控制事物的处理器,TransactionHandler,,,假如,假如,假如,,,,,,,,,,,,,,,你能想到什么,动态代理就能代理什么,,,功能很是强大。。
    不知道LZ是不是有点明白什么是动态代理了。也晚了,也饿了,吃饭去了,有问题继续提啊,。。
      

  9.   

    1、代理的意思:本来应该自己做的事情,因为没有某种原因不能直接做,只能请别人代理做。被请的人就是代理。比如春节买票回家,由于没有时间,只能找票务中介来买,这就是代理模式。2、以下的例子将简单的模拟代理模式     比如一个信息管理系统,有的用户有浏览的权限,有的用户有修改和编辑的权限,有的用户除了以上的权限,还有删除的权限。(1) 最普通的做法:    public class ViewAction {
       
            public void doAction(){
                String permission = "view";
                if(permission.equals(Constants.PRIMISSION_VIEW)){
                    System.out.println("you could view information");                 //........做view的动作
                }
            }
        }    其他的动作和浏览的动作差不多。但这样做有两个缺点:(一)它把权限的控制的执行的动作放在一起,两者的功能混在一起,造成了维护和修改的不方便。不满足单一职责原则。(二)客户端调用的是具体的实现类,造成了扩展和运行时调用的困难,不满足依赖颠倒原则(最下面补充说明)。(2)初步代理    因此对以上的类做了重新设计,通过代理实现。和买车票一样,代理类必须先检测权限,再执行动作。修改后的密码如下。     接口类(首先设计一个接口,满足依赖颠倒原来):    public interface IAction {
            public void doAction();
        }      动作执行类(相当于买车票的动作),动作的真正执行者:    public class ViewAction implements IAction {
            public void doAction() {
                System.out.println("you could view the information");
                //............做view的动作
            }
        }      代理类(ViewActionProxy )除了做了客户要做的doAction()动作,还做了权限的判断。而ViewAction只做了核心动作,满足了单一原则。    public class ActionProxy implements IAction {
            private ViewAction viewAction = new ViewAction();
            public void doAction() {
                if(Permission.getPermission(userid).equals
                  (Constants.PERMISSION_VIEW)){
                    viewAction.doAction();
                 }
            }
        }       总之,客户段通过调用这个代理类执行动作,这个代理类通过将权限判断和具体的动作执行分开。实现了单一原则。代理类又叫委派,即代理类并没有亲自执行,而是委派给另一个类来执行。ProxyViewAction并没有亲自执行,而是给ViewAction执行。     再看看ViewActionProxy,他不仅依赖于抽象接口IAction,而且依赖具体类ViewAction。这样对系统的扩展性很不好。因为我们还有add,delete,update动作等。(1)我们可以为每个动作都写一个代理类,可是每个代理类都做相同的动作:先进行权限的判断,再执行具体的动作。所以我们对ViewAction具体类再一次抽象,使得代理类(ViewActionProxy)只依赖于接口IAction,而不依赖具体类ViewAction。(3)代理改进:将代理类脱离动作的具体执行类。   要实现这个功能,必须让代理类的具体实现去掉(private ViewAction viewAction = new ViewAction();),而让代理类的使用者,再使用的时候提供具体的实现类,这个就是依赖注入。    public class ViewActionProxy implements IAction {
            private IAction action ;
            public void setAction(IAction action) {
                this.action = action;
            }
           
            public void doAction() {
                if(Permission.getPermission(userid).
                  equals(Constants.PERMISSION_VIEW)){
                    action.doAction();
                }
            }
        }     这样我们能就将所有使用了IAction接口的具体类都通过这个代理类来代理。比如AddAction、DeleteAction、 UpdateAction都可以用这个代理类来代理。(4)动态代理:没有实现接口的类的某些方法也可以使用代理。分别添加增加add,delete,update方法,可是每个方法体内都做相同的动作:先进行权限的判断,再执行具体的动作。        如果我们没办法将所有的类抽象出一个统一的接口,我们可能有多个接口。但是按照上面的方法,每个代理都必须为每个接口写一个相应的代理类。没有统一的接口情况下,对一些零散的对象的某些动作使用代理模式。       动态代理的核心是InvocationHandler,要实现动态代理,就必须实现这个接口。这个接口的委派任务是在public Object invoke(Object proxy, Method method, Object[] args)方法中实现的。invoke的主要流程如下:     ...........................//在调用核心动作前的作一些动作。      m.invoke(obj, args); //调用核心动作。     ............................//在调用核心动作后的做一些动作。       我们看到动态代理是通过反射机制来调用核心功能m.invoke(obj, args); 这个反射机制使得我们不依赖任何一个具体的接口,而是依赖具体的类。动态代理类的具体实现如下:    public class ActionProxy implements InvocationHandler {
            private Object action;
           
            public ActionProxy(Object action){
                this.action = action;
            }
               
            public static Object getInstance(Object action){
                return Proxy.newProxyInstance(
                                         action.getClass().getClassLoader(),
                                         action.getClass().getInterfaces(),
                                         new ActionProxy(action));             //自动生成相应的代理类,且类里面有个变量是ActionProxy对象,当客户端调用这个代理类的方法时候,代理类会调用它的ActionProxy 变量的invoke方法,因此每次调用了代理类,就可以在方法执行前和方法执行后加入特定的执行内容(事务或日志等)。
             }
            
             public Object invoke(Object proxy, Method method, Object[] args)
               throws Throwable {
                  Object result;
                  System.out.println("befor method:"+method.getName());
                  result = method.invoke(action, args);
                  System.out.println("after method:"+method.getName());
                  return result;
             }
        }      代理类必须实现InvocationHandler接口,getInstance()方法获得代理类的实例(实现了IAction接口)的对应代理,invoke方法实现了简单的代理方法。客户段代码如下:    public class TrasasactionTest {
            public static void main(String[] args) {
                IAction action = (IAction) ActionProxy.getInstance(new ViewAction());
                action.doAction();
            }
        }     由上得出,代理对于接口的依赖转移到客户端,代理不必再实现特定的接口。因此ActionProxy也可以用于任何的接口。            ITestService service = (ITestService ) ActionProxy.getInstance(new TestServiceImpl());
                service .doTest();//只要TestServiceImpl实现ITest,就可以。(5)在委派前的动作和委派后的动作在不同的代理类不用,可是代理类的生成和其他的内容都是相同的。所以我们可以用Template模式对代理类进行进一步的优化。      生成代理类的基类的代码如下:public abstract class BaseProxy implements InvocationHandler {private Object target;public Object getTarget() {
       return target;
    }public BaseProxy(Object target){
       this.target = target;
    }public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {
            Object result;
            doBefore();
            result = method.invoke(target, args);
            doAfter();
       return result;
    }
    public abstract void doBefore();
    public abstract void doAfter();
    }代理类基类的具体实现如下:    public class ProxyImpl extends BaseProxy {
            public ProxyImpl(Object target) {
                super(target);
            }        //委派前的动作
            public void doAfter() {
                System.out.println("do before method");
            }       //委派后的动作
            public void doBefore() {
                System.out.println("do after method");
            }
        }      因此,在OOP中,doBefore(),核心动作,doAfter()可能这3个动作在所有的类中都存在,但是doBefore,doAfter的内容都是相同的,而核心动作确实不相同的。因此把doBefore和doAfter提取出来,共同设计,这是AoP的基础。AoP的一个重要特点是找出哪些方法需要执行doBefore和doAfter,哪些不用。