java.lang.reflect.Proxy :Prpxy.newProxyInstance()
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException
>方法作用:动态创建 实现了interfaces数组中所有指定接口的 实现类对象。
(该方法动态生成一个类,该类实现了接口数组中的所有接口,最后创建这个类的对象。以前都是专门写一个class类,然后在main方法中new一个对象。而现在是通过一个方法来创建类,根据实现的接口不同,创建出的类也不同,这也是“动态”的体现)
>参数:
1.ClassLoader:类加载器。用来加载类,将.class文件加载到内存中,形成Class对象。
Java中通过Person p = new Person();来创建对象。实际创建对象的过程中有以下流程:
①通过ClassLoader将Person.class加载到内存中,将其变成Class<Person>对象;然后执行静态代码块和静态初始化语句
②执行new方法,创建一个空白对象
③调用构造器
④子类调用父类构造器
⑤构造器执行过程:执行构造器代码块和初始化语句;然后执行构造器中内容
2.Class[ ] interfaces:指定要实现的接口数组
3.InvocationHandler:代理对象的所有方法(个别不执行) ,内容都是调用InvocationHandler中的invoke()方法
InvocationHandler h = new InvocationHandler() {
public Object invoke(Object arg0, Method arg1, Object[] arg2)
throws Throwable {
return null;
}
};
invoke()方法在调用代理对象所实现的接口中的方法时被调用。
可以从中找出关系,当返回的代理对象在调用接口中的方法时,会自动调用InvocationHandler中的invoke()方法,此时,将代理对象赋值给invoke参数中的proxy;aaa方法赋值给参数method;方法中的参数赋值给args。此时invoke返回的Object赋值给result
>参数:
1.Object proxy:当前代理对象
2.Method method:当前被当用的方法
3.Object[] args:实参
public interface Waiter {
public void service();
}
public class ManWaiter implements Waiter {
public void service() {
System.out.println("服务");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Demo2 {
public void fun(){
Waiter manWaiter = new ManWaiter();
//给出三个参数来创建动态代理对象
ClassLoader loader = this.getClass().getClassLoader();
Class[] interfaces = {Waiter.class};
InvocationHandler h = new WaiterInvocationHandler(manWaiter);
//得到代理对象,代理对象实质就是在目标对象的基础上进行增强
Waiter waiterProxy = (Waiter)Proxy.newProxyInstance(loader, interfaces, h);
waiterProxy.service();
}
}
class WaiterInvocationHandler implements InvocationHandler{
private Waiter waiter;//目标对象
public WaiterInvocationHandler(Waiter waiter){
this.waiter = waiter;
}
ManWaiter manWaiter = new ManWaiter();
public Object invoke(Object arg0, Method arg1, Object[] arg2)
throws Throwable {
System.out.println("上菜");
waiter.service();
System.out.println("收小费");
return null;
}
}
举例:给一个计算器添加日志管理。
public interface Calculator {
public int add(int i,int j);
public int sub(int i,int j);
public int mul(int i,int j);
public int div(int i,int j);
}
import com.cuco.inter.Calculator;
public class MyMathCalculator implements Calculator {
public int add(int i, int j) {
// TODO Auto-generated method stub
return i+j;
}
public int sub(int i, int j) {
// TODO Auto-generated method stub
return i-j;
}
public int mul(int i, int j) {
// TODO Auto-generated method stub
return i*j;
}
public int div(int i, int j) {
// TODO Auto-generated method stub
return i/j;
}
}
/*
* 为Calculator.java生成代理对象的类
*
* */
public class CalculatorProxy {
public static Calculator getProxy(final Calculator calculator){
//为传入的对象创建动态代理对象
//方法执行器,帮目标对象执行目标方法
InvocationHandler h = new InvocationHandler(){
/*
* Object proxy:代理对象:给JDK使用,任何时候不要使用该对象
* Method method:当前将要执行目标对象的方法
* Object[] args:方法调用时,外界传入的实参
* */
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//利用反射执行目标方法
//目标方法执行后的返回值
LogUtils.logStart(method, args);
Object result = method.invoke(calculator, args);
LogUtils.logReturn(method, result);
return result;
}
};
Class<?>[] interfaces = calculator.getClass().getInterfaces();
ClassLoader loader = calculator.getClass().getClassLoader(); //目标对象的类加载器
Object proxy = Proxy.newProxyInstance(loader,interfaces,h);
return (Calculator)proxy;
}
}
public class LogUtils {
public static void logStart(Method method, Object[] args){
System.out.println("["+method.getName()+"]方法开始执行,使用参数列表["+Arrays.asList(args)+"]");
}
public static void logReturn(Method method, Object result){
System.out.println("["+method.getName()+"]方法执行结束,执行结果为["+result+"]");
}
}
public class AOPTest {
/*
* 有了动态代理:日志记录可以更加强大,不需要将日志记录放在执行方法中,和业务逻辑解耦
*
* */
@Test
public void test() {
Calculator calculator = new MyMathCalculator();
calculator.add(2, 4);
System.out.println("-------------------------------------------");
Calculator proxy = CalculatorProxy.getProxy(calculator);
proxy.add(5, 6);
}
}