动态代理详解

动态代理的作用
通过反射调用代理对象,让其帮我们实现一些非常频繁的操作,如:权限校验和日志记录
代理的实现原理:在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口通过使用这个类和接口就可以生成动态代理对象。这里只能针对接口实现代理,后期cglib可以实现类的代理
代理的实现过程:既然是代理,顾名思义,就是代替某个类或接口去实现某个功能,也就是说,我代理了你,我就具备了你的功能。怎么才能具有其他类或接口的功能呢:要么是继承自类,要么是实现接口。而我们已经知道,此处只能代理接口。所以在造该代理对象时,肯定是让其实现了被代理的接口。而实现了接口还只是第一步,我还要提供一些特有的功能所以再创建完动态代理对象以后至少要实现这两个目的:实现被代理的功能、并提供特殊功能。
具体步骤:首先由Proxy类的静态方法newProxyInstance创建动态代理对象

public static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)

而要创建该对象,需要3个参数ClassLoader loader:定义了由哪个ClassLoader对象来对生成的代理对象进行加载Class[] interfaces:表示的是我将要给我需要代理的对象提供一组什么接口InvocationHandler h:既然一个指明了加载器,一个指明了接口,那么这个就是具体实现功能的方法了。InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上每一个动态代理类都必须要实现InvocationHandler这个接口,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke 方法来进行调用

public Object invoke(Object proxy, Method method, Object[] args)InvocationHandler

接口中invoke方法的三个参数:proxy:代表动态代理对象method:代表正在执行的方法args:代表调用目标方法时传入的实参由此可知,实际在实现InvocationHandler接口重写invoke方法时,所需要的三个参数都不要我们给出

public interface StudentDao {  
  
    public abstract void login();  
      
    public abstract void regist();  
}  
public class StudentDaoImpl implements StudentDao {  
  
    @Override  
    public void login() {  
        System.out.println("登录功能");  
    }  
  
    @Override  
    public void regist() {  
        System.out.println("注册功能");  
    }  
  
}  
/* 
 * 由于该对象要重写的方法中会调用代理对象的方法,所以需要把被代理的目标对象以参数的方法传入 
 * 然后使用反射调用目标对象的方法 
 */  
public class MyInvocationHandler implements InvocationHandler {  
  
    private Object target;  //目标对象  
    public MyInvocationHandler(Object target){  
        this.target = target;  
    }  
      
    @Override  
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        //代理要提供的特殊功能  
        System.out.println("权限校验");  
          
        //通过反射执行目标对象的方法  
        method.invoke(target, args);  
          
        //代理要提供的特殊功能  
        System.out.println("日志记录");  
        return null;//如果底层方法返回类型为 void,则该调用返回 null  
    }  
}  

创建动态代理对象并实现功能

import java.lang.reflect.Proxy;  
  
/* 
 分析: 
 登录注册属于用户的扩展功能,用接口实现 
 然后重写抽象方法,实现接口 
 创建实现InvocationHandler接口的对象作为Proxy的参数使用(其实,底层方法的调用即特殊功能的实现都是通过该对象实现的) 
 由Proxy的静态方法创建动态代理对象,由于返回值是Object所以需要向下转型 
 */  
public class ProxyDemo {  
    public static void main(String[] args) {  
        // 创建被代理对象  
        StudentDao st = new StudentDaoImpl();  
        // 创建实现InvocationHandler接口的对象  
        MyInvocationHandler mi = new MyInvocationHandler(st);  
        // 创建动态代理对象  
        StudentDao proxy = (StudentDao) Proxy.newProxyInstance(st.getClass().getClassLoader(), st.getClass().getInterfaces(), mi);  
        //用动态代理对象调用方法  
        proxy.login();  
        proxy.regist();  
    }  
}

你可能感兴趣的:(动态代理详解)