动态代理
动态代理,是在不改变源码的基础上,对已有的代码增强(它是aop思想的实现技术)
动态代理分类
1.基于接口的动态代理
要求:被代理类最少实现一个接口
* 提供者jdk官网
* 创建代理对象的方法:proxy.newproxyinstance(classloader,calss[],invocationhandler)
* 参数的含义:
* classloader:类加载器,和被代理对象使用相同的类加载器,一般都是固定写法
* class[]:字节码数组,被代理类实现的接口。(要求代理对象和被代理对象具有相同的行为)。一般都是固定写法
* invocationhandler 它是一个接口,就是我们用于提供增强代码的,我们一般都 是写一个该接口的实现类,实现类可以是一个匿名内部类
* 它的含义就是如何代理。此处的代码只能是谁用谁提供
* 策略模式:
* 使用要求:数据已经有了
* 目的明确
* 达成目标的过程就是策略
* 在dbutils中的resultsethandler就是策略模式的具体应用。
*
示例:
cn.pro.proxy.IActor
package cn.pro.proxy;
public interface IActor {
public void basicAct(float money);
public void dangerAct(float money);
}
cn.pro.proxy.Actor
package cn.pro.proxy;
public class Actor implements IActor{
public void basicAct(float money){
System.out.println("拿到钱,开始基本的表演" + money);
}
public void dangerAct(float money){
System.out.println("拿到钱,开始危险的表演" + money);
}
}
cn.pro.proxy.Client
package cn.pro.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Client {
/**
*
* 模拟一个剧组
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
final Actor ac = new Actor();
IActor proxyactor = (IActor) Proxy.newProxyInstance(Actor.class.getClassLoader(),
Actor.class.getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
/*被代理对象的任何方法都会经过该方法,该方法有拦截的功能
* 方法的参数
* Object proxy, 代理对象的引用,不一定每次都会有
*
* Method method,当前执行的方法
*
* Object[] args 当前执行方法所需的参数
*返回值 当前执行方法的返回值
*
*
*
*
* */
Object rtValue =null;
//1取出执行方法中的参数
float money = (Float) args[0];
//2判断当前执行的是什么方法。
//如果多于一万 则开始普通的表演
if("basicAct".equals(method.getName())){
if (money >10000){
//执行方法
rtValue = method.invoke(ac, money);
}
}
//如果多于5万,则开始危险的表演
if("dangerAct".equals(method.getName())){
if(money>50000){
rtValue = method.invoke(ac, money);
}
}
return rtValue;
}
} );
proxyactor.basicAct(10000f);
proxyactor.dangerAct(50000f);
proxyactor.basicAct(20000f);
proxyactor.dangerAct(60000f);
}
}
此动态代理,对参数进行了限定,如果一般表演的费用没有10000 或者危险表演的费用没有60000则不执行方法,没有表演。
总结:动态代理是对参数进行策略,结合if语句,如果某方法的某参数等于或大于某值则。。。。
基于子类的动态 代理
* 要求:被代理类不能是最终类。不能被final修饰
* 提供者是第三方CGLIB
* 涉及的类:enhancer
* 创建代理对象的方法:create(Class,callback)
* 参数的含义
* class:被代理对象的字节码
* callback:如何代理,它和invocationhandler作用是一样的,它也是一个接口,我们一般使用该接口的子接口,
* 它的子接口是methodinterceptor
* 在使用时,也是创建该接口的匿名内部类
导包:
cglib.Actor
package cglib;
public class Actor {
public void basicAct(float money){
System.out.println("拿到钱,开始基本的表演" + money);
}
public void dangerAct(float money){
System.out.println("拿到钱,开始危险的表演" + money);
}
}
cglib.Client
package cglib;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class Client {
/**
*
* 模拟一个剧组
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
final Actor ac = new Actor();
/*
*
* 基于子类的动态代理
* 要求:被代理类不能是最终类。不能被final修饰
* 提供者是第三方CGLIB
* 涉及的类:enhancer
* 创建代理对象的方法:create(Class,callback)
* 参数的含义
* class:被代理对象的字节码
* callback:如何代理,它和invocationhandler作用是一样的,它也是一个接口,我们一般使用该接口的子接口,
* 它的子接口是methodinterceptor
* 在使用时,也是创建该接口的匿名内部类
*
*
* */
Actor cglibactor = (Actor) Enhancer.create(Actor.class, new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodproxy
) throws Throwable {
/*执行被代理对象的任何方法都会进过该方法,它和基于接口动态代理的invoke方法作用是一模一样的
*
* 方法的参数
* 前面三个参数与基于接口的动态代理参数一样
* MethodProxy arg3 :当前执行方法的代理对象,一般不用
*
* */
// TODO Auto-generated method stub
Object rtValue =null;
//1取出执行方法中的参数
float money = (Float) args[0];
//2判断当前执行的是什么方法。
//如果多于一万 则开始普通的表演
if("basicAct".equals(method.getName())){
if (money >10000){
//执行方法
rtValue = method.invoke(ac, money);
}
}
//如果多于5万,则开始危险的表演
if("dangerAct".equals(method.getName())){
if(money>50000){
rtValue = method.invoke(ac, money);
}
}
return rtValue;
}
});
cglibactor.basicAct(10000f);
cglibactor.dangerAct(60000f);
}
}