java代理有jdk动态代理、cglib代理,这里只说下jdk动态代理,jdk动态代理主要使用的是java反射机制(既java.lang.reflect包)
对类增强的3种方式:
继承
装饰者
动态代理
动态代理:
一个类不能或不适合直接访问目标对象,可以使用代理对象。
动态代理的目标:
对目标对象的功能增强。
动态代理:程序运行时,使用JDK提供工具类(Proxy),动态创建一个类,此类一般用于代理。
代理:你 -- 代理(增强) -- 厂商
代理类:目标类:被代理的
动态代理使用前提:必须有接口
Object proxyObj= Proxy.newProxyInstance(参数1,参数2,参数3);
参数1:ClassLoader,负责将动态创建类,加载到内存。当前类.class.getClassLoader();
参数2:Class[] interfaces ,代理类需要实现的所有接口(确定方法),被代理类实例.getClass().getInterfaces();
参数3:InvocationHandler, 请求处理类,代理类不具有任何功能,代理类的每一个方法执行时,调用处理类invoke方法。
voke(Object proxy ,Method ,Object[] args)
参数1:代理实例
参数2:当前执行的方法
参数3:方法实际参数。
以下是个动态代理的小demo便于理解
必须要有的接口:
public interface KindWomen {
void throwEye(double money);
void doSomeThing(double money);
}
实现接口的类,也就是被代理的类,被增强的类:
public class PJL implements KindWomen {
@Override
public void throwEye(double money){
System.out.println("潘金莲抛媚眼"+money);
}
@Override
public void doSomeThing(double money){
System.out.println("潘金莲..."+money);
}
}
代理工厂类,也就是实现动态代理的核心类:
public class ProxyFactory {
public static Object getProxy(final Class clazz) {
//参数一:被代理对象的类加载器,固定写法
//参数二:被代理对象实现的接口,固定写法
//参数三:使用的是策略模式,固定写法,如何调用真实对象的方法
Object obj = Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
@Override
//代理对象调用的任何方法都会触发此方法执行
//参数一:代理对象本身的引用,一般不用
//参数二:代理对象调用的方法
//参数三:代理对象调用的方法的参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//前置增强
args[0]=Double.parseDouble(args[0]+"")/2;
method.invoke(clazz.newInstance(), args[0]);//调用真实对象中的方法
//后置增强
System.out.println("后置增强!!!");
return null;
}
});
return obj;
}
}
操作类,看效果:
public class XMQ {
public static void main(String[] args) {
KindWomen wangPo = (KindWomen) ProxyFactory.getProxy(PJL.class);
wangPo.throwEye(10);
wangPo.doSomeThing(100);
}
}
执行代码,效果如下:
潘金莲抛媚眼5.0
后置增强!!!
潘金莲...50.0
后置增强!!!