AOP
动态代理
租房的时候,房屋中介就是代理(筛选符合自己要求的房子,再供自己选择)。
-
代理也需要和自己有相同的所有能力(自己有看房的能力,中介也有)。
-
在程序中,代理是一个对象。这个对象由一个类产生,这个类本身就是动态产生。
-
这个类本身不会被创建,在程序运行时动态产生。
-
InvocationHandler提供生成代理类的功能,InvocationHandler不是代理类,是帮助生成动态代理类的一个类。
代码分析
public class MyInvocationHandler implements InvocationHandler {
//接收委托对象
private Object object=null;
//返回代理对象
public Object bind(Object object){ //传入委托对象
this.object=object;
return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName()+"方法的参数是"+ Arrays.toString(args));
Object result=method.invoke(this.object,args);
System.out.println(method.getName()+"方法的结果是"+ result);
return result;
}
}
什么是委托对象,什么是代理对象
在租房过程中,“我”就是委托对象,“中介”就是代理对象。
具体工程中,计算器就是委托对象,打印日志对应工作的对象就是代理对象。
为什么要把委托对象传入代理对象中
因为要执行的业务方法要让本身执行。
为什么要返回代理对象
由MyInvocationHandler类创建一个动态代理类,再由动态代理类创建动态代理对象。
我们可以直接操作代理对象。
Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
返回一个代理实例(代理对象),代理对象的创建需要类的支持,但这个类是动态创建的,所以要用类加载器添加进去。
Proxy.newProxyInstance 返回一个新的代理实例
object.getClass() 获取委托对象的运行实类
getClassLoader()获取类加载器
委托类的全部功能,代理类需全部拥有。
getInterfaces()获取实类中的所有接口
通过getInterfaces()将委托对象的所有接口交给代理类,代理类动态创建和委托对象功能一样的类。
this 通过MyInvocationHandler创建一个代理对象
invoke(Object proxy, Method method, Object[] args)
用于剥离核心业务代码和日志信息
method就是委托对象中核心业务的方法
method.getName() 拿到委托对象方法名。
args就是委托对象中核心业务的参数
Arrays.toString(args)把数组转化成字符串形式输出
Object result=method.invoke(this.object,args)
method.invoke为当前目标方法,invoke为通过反射机制调用。
代码分析
public class Test {
public static void main(String[] args) {
Cal cal=new CalImpl();
MyInvocationHandler myInvocationHandler=new MyInvocationHandler();
Cal cal1= (Cal) myInvocationHandler.bind(cal);
cal1.add(3,3);
cal1.div(3,3);
cal1.sub(3,3);
cal1.mul(3,3);
}
}
Cal cal=new CalImpl()
MyInvocationHandler myInvocationHandler=new MyInvocationHandler()
创建对象
Cal cal1= (Cal) myInvocationHandler.bind(cal)
myInvocationHandler.bind(cal);通过myInvocationHandler中的bind方法,传入委托对象cal,会返回一个代理对象。
cal1.add(3,3)
调用代理对象,实现日志信息的插入与方法的实现。
程序执行完整流程
-
首先实例化委托对象 Cal cal=new CalImpl(); (创建一个“我“)
-
MyInvocationHandler myInvocationHandler=new MyInvocationHandler(); (实例化InvocationHandler,通过InvocationHandler创建代理对象)
Cal cal1= (Cal) myInvocationHandler.bind(cal);(”我“去买房,找了一个中介公司,中介公司派了一个人和我对接)
-
public Object bind(Object object)(记录委托对象)
Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this); (返回代理对象)
-
Cal cal1= (Cal) myInvocationHandler.bind(cal);(cal1就是创建好的代理对象,具备cal的所有功能)
-
cal1.add(3,3); (调用方法)
-
public Object invoke(Object proxy, Method method, Object[] args)(proxy就是cal1,method就是add,args就是3,3)
-
System.out.println(method.getName()+“方法的参数是”+ Arrays.toString(args));(add方法传入)
-
Object result=method.invoke(this.object,args);(由委托对象this.object调用方法)