整体步骤概述:
1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法
2.创建需要被代理接口和实现类
3.通过Proxy的静态方法newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)创建一个代理
4.通过代理调用方法
5.生成的动态代理类会调用InvocationHandler实现类中的invoke方法
6.invoke方法中我们可以选择执行被代理实现类的方法,并在其前后进行处理
具体实现方法:
1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法
package com.willow.sunday.common.study;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 调用处理器实现类
* 每次生成动态代理类对象时都需要指定一个实现了该接口的调用处理器对象
*/
public class InvocationHandlerImpl implements InvocationHandler {
/**
* 这个就是我们要代理的真实对象
*/
private Object subject;
/**
* 构造方法,给我们要代理的真实对象赋初值
* @param subject
*/
public InvocationHandlerImpl(Object subject)
{
this.subject = subject;
}
/**
* 该方法负责集中处理动态代理类上的所有方法调用。
* 调用处理器根据这三个参数进行预处理或分派到委托类实例上反射执行
* @param proxy 代理类实例
* @param method 被调用的方法对象
* @param args 调用参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.err.println("方法执行之前");
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
//在此处执行被代理对象的方法
//mybatis的原理就是将JDK生成的动态代理类注入到Dao接口中,在Dao接口的动态代理类执行时拦截到,转为调用处理器中的invoke方法,
//并在invoke方法中根据被调用的方法名称,去调用了mapperStatement对应的方法
Object returnValue = method.invoke(subject, args);
System.err.println("方法执行之后");
return returnValue;
}
}
2.创建需要被代理接口和实现类
package com.willow.sunday.common.study.DynProxy;
/**
* 需要被动态代理的接口
*/
public interface Subject {
/**
* 你好
*
* @param name
* @return
*/
public String SayHello(String name);
/**
* 再见
*
* @return
*/
public String SayGoodBye();
}
package com.willow.sunday.common.study.DynProxy;
/**
* 被动态代理的接口的实现类
*/
public class SubjectImpl implements Subject {
@Override
public String SayHello(String name) {
return "Hello:"+name;
}
@Override
public String SayGoodBye() {
return "bye";
}
}
3.通过Proxy的静态方法newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)创建一个代理
package com.willow.sunday.common.study.DynProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String [] args){
Subject s = new SubjectImpl();
/**
* InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
* 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用.
* 即:要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法
*/
InvocationHandler ih = new InvocationHandlerImpl(s);
ClassLoader classLoader = s.getClass().getClassLoader();
Class[] interfaces = s.getClass().getInterfaces();
/**
* 该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
*/
Subject proxyS = (Subject) Proxy.newProxyInstance(classLoader,interfaces,ih);
System.err.println("动态代理对象的类型:"+proxyS.getClass().getName());
System.err.println(proxyS.SayHello("willow"));
}
}