java动态代理的理解
package com.atguigu.java3;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理的举例 代理模式:代理类,被代理类,接口
*
*
* @author yangzhnahang
* @create 2019-08-17-18:42
*/
//代理类之一
interface Human{
String getBelif();
void eat(String food); //快捷键加分号: Shift+Ctrl+Enter
}
//被代理类 实现接口
class SuperMan implements Human{
@Override
public String getBelif() {
return "I believe I can fly!";
}
@Override
public void eat(String food) {
System.out.println("我喜欢吃" + food);
}
}
/**
* 要想实现动态代理,需要解决的问题?
* 问题一: 如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象
* 问题二: 当通过代理类的对象调用方法时,如何动态的去调用被代理类的同名方法
*/
/**
* 思路:
*
* 本类使用过程:
* 通过class ProxyFactory{}类时,在调用getProxyInstance(Object obj)的时候
* 先造一个 被代理类的对象, 顺便把class MyInvocationHandler implements InvocationHandler{}
* 的
* public void bind(Object obj){ //这里相当于做了一个实例化
* this.obj = obj;
* } 给实例化了。
*
* 实例化之后,在通过Proxy.newProxyInstance(obj.getClass().getClassLoader(),
* obj.getClass().getInterfaces(),handler);
* 代理类调用
* public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
* 调用结束之后就得到了,对象,方法 在通过
* method.invoke(被代理类的对象,这个参数三就是同名method的参数);
* }
*
* 由于invoke()有一个返回值,因此,我们采用Object方法去接收
*
*
*/
class ProxyFactory{
//问题一: 调用此方法返回一个代理类的对象 这里要声明成Object的类型,
// 否则写成Human又写死了,成静态了
public static Object getProxyInstance(Object obj){ //obj:被代理类的对象
MyInvocationHandler handler = new MyInvocationHandler();
/**
* new MyInvocationHandler(); 造出一个对象之后,
* 就可以用handler.bind(obj);这个方法了
* 这个调用相当于给
* class MyInvocationHandler implements InvocationHandler{}
* 中的 private Object obj; 进行赋值
*
* Object 即代理类的类型
*/
handler.bind(obj);
/**Proxy.newProxyInstance 创建代理类的 对象
* obj.getClass().getClassLoader() 找出类的对象由哪个加载器加载
* 你是哪个加载器加载的,我跟你一样
*
* obj.getClass().getInterfaces() 声明代理类和被代理类用的 同一个接口
* 这里先找到被代理类实现的是什么接口,把接口放到代理类中,
* 这样可以保证接口一致
*
* 第三个参数放的是同名方法,由于这个参数是一个接口,所以要写上一个实现类
* class MyInvocationHandler implements InvocationHandler{}
*
* Proxy.newProxyInstance(代理类对象,代理接口,被代理类对象);
*
* 因此,一旦调用class ProxyFactory{
* interface Human{
* String getBelif();
* void eat(String food); //快捷键加分号: Shift+Ctrl+Enter
* }
* 中的eat();方法,就相当于直接调用 handler的
* invoke(Object proxy, Method method, Object[] args) 这个方法
*
*
*/
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),handler);
}
}
/**Proxy.newProxyInstance(obj.getClass().getClassLoader() 由于这里生成了代理类的对象,
* 这个对象调用方法时,调用了 第三个参数Xxx 这个参数即 MyInvocationHandler类型的对象
* 即使用了Proxy.newProxyInstance这个方法就会调用第三个参数,而这个参数是对象,
* 这个MyInvocationHandler类型的对象中含有
*invoke(Object proxy, Method method, Object[] args) throws Throwable {}
* 这个方法,
*
* 因此需要在class ProxyFactory{}中在创建一个对象,对象类型是MyInvocationHandler的
*/
class MyInvocationHandler implements InvocationHandler{
/**method.invoke();要求我们声明一个被代理类,作为第一个参数传进去
* 这个被代理类也不能写死了,即不写成human,要写成动态的,Object的
* 赋值时,需要使用被代理类的对象进行赋值
*
*/
private Object obj;
//赋值可以采用构造器赋值,也可以采用方法赋值,这里用方法赋值
/**
* 造完对象之后,可以在class ProxyFactory{}中写上
* handler.bind() private Object obj;给赋值,
* 如果不赋值,则 method.invoke()就成了空指针了
*
*
*
* 赋值,赋的是被代理类的对象
* public static Object getProxyInstance(Object obj){
* 中参数 obj, 即被代理类的对象就是要赋的值
*
* 这里意味着:
*
*
* @param obj
*/
public void bind(Object obj){ //这里相当于做了一个实例化
this.obj = obj;
}
/**
* 下面方法中invoke()体现一个动态的性质。
* 当我们通过代理类的对象,调用方法a时,会自动的调用如下的方法:invoke()
* 将被代理类要执行的方法a的功能就声明在invoke()方法中
*
* Object proxy参数:即代理类的对象
* Method method 代理类的对象是什么方法这里就是什么方法
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/**
* 通过反射调用 public static Object getProxyInstance(Object obj){
* //obj:被代理类的对象 这里的方法(这个方法收集了 代理类,接口,被代理类)
* 本质上 method.invoke(obj, args); 这句代码invoke的是被代理类的对象,
* 但是
* @Override
* public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
* 这里没有提供有 被代理类的对象
* 因此,在class MyInvocationHandler implements InvocationHandler{
* 里边再声明一个,但是要写成 Object类型,否则就写死了,不符合动态本质
*
*/
//method:即为代理类对象调用的方法,此方法也作为被代理类对象要调用的方法
//obj:被代理类的对象
Object returnValue = method.invoke(obj, args);
//上述方法(代理类对象调用的方法)的返回值就作为当前类的invoke()的返回值
return returnValue;
}
}
public class ProxyTest {
//测试了
public static void main(String[] args) {
//第二步:再传一个被代理类的对象
SuperMan superMan = new SuperMan();
//先创建一个 代理类的对象 proxyInstance:即代理类的对象 把被代理类对象放进来
Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
//当通过代理类对象调用方法时,会自动的调用,并且时动态的调用被代理类中同名方法
String belif = proxyInstance.getBelif();
/**
* 实质:调用proxyInstance.getBelif();这个方法时,自动调用了
* public Object invoke(Object proxy, Method method,
* Object[] args) throws Throwable {}中的method.invoke(obj, args);
*
* 这里的 method 就是 getBelif() 由于getBelif()中没有参数,所以相当于空了
*
*
* 下面的也一样: 调用
* proxyInstance.eat("四川麻辣烫"); 这个方法时,自动调用了
* public Object invoke(Object proxy, Method method,
* Object[] args) throws Throwable {}中的method.invoke(obj, args);
* 这里的 method 就是 eat("四川麻辣烫");
* 这里的 四川麻辣烫 即args即实参。
*
* 通过测试可以看到:我们调用这两个方法
* proxyInstance.getBelif();
* proxyInstance.eat("四川麻辣烫");
* 实质都是被代理类中的两个方法
*
*
* 当通过代理类调用方法时,会自动调用被代理类中的同名方法。
*/
System.out.println(belif);
proxyInstance.eat("四川麻辣烫");
NikeClothFactory nikeClothFactory = new NikeClothFactory();
ClothFactory proxyClothFactory = (ClothFactory)
ProxyFactory.getProxyInstance(nikeClothFactory);
/**
* 创建被代理类对象: nikeClothFactory
* ClothFactory proxyClothFactory = (ClothFactory)
* ProxyFactory.getProxyInstance(nikeClothFactory);
* 这句代码动态创建了代理类 的对象 ,
* 同时声明成接口类型的ClothFactory
*/
proxyClothFactory.produceCloth();
/**
*proxyClothFactory.produceCloth();动态的调用nikeClothFactory
* 这个对象nikeClothFactory中的方法
*
* 说明:
*nikeClothFactory明明是被代理类的中方法,
* 但是我们看到可以通过 代理类对象proxyClothFactory
* 来代理执行的。
*
*
* 此时,我只需要提供被代理类,接口,然后就可以动态的创建代理类,
* 用代理类来执行就可以了
*/
}
}
java动态代理类理解
原创
©著作权归作者所有:来自51CTO博客作者wx5cf7b29acc63c的原创作品,请联系作者获取转载授权,否则将追究法律责任
下一篇:java静态代理代码解析记录
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
Cglib动态代理
cglib动态代理
cglib动态代理 -
Spring开发:动态代理的艺术与实践
本文深入分析了JDK和CGLIB两种动态代理技术在Spring框架中的应用。
动态代理 java JDK spring -
深入理解Java动态代理
动态代理就是一个中介,把我们想执行的代码给它,在不侵入原有代码的情况下,能够完整执行下去。
java 开发语言 System 对象创建 -
java动态代理--代理接口无实现类
[java] view plain copypackage cn.proxy;
java反射 java System 方法调用 -
深入理解JDK动态代理
代理模式想不想听
ide 限流 代理类 动态代理 java