动态代理

学无止境,学无止境,根本停不下来。

什么是动态代理?

现在有一个Student类,里面有吃饭方法。

public class Student{
	public void eat(){
		System.out.println("吃饭");
	}
}

现在我要给这个方法添加其他功能,比如:

System.out.println("拿筷子");
System.out.println("盛饭");

按以前所学,我们只能把这两句话放入eat()方法中,直接修改代码,被称为侵入式修改。在一个成熟的项目中,我们很少会这么去干,因为可能会整个项目坍塌。那我既不能修改原有的代码,还要增加新的功能,那我怎么办?此时我们就得去找一个代理,什么是代理,说白了就是中介公司,他会帮你先去做拿筷子和盛饭的这些准备工作,等真正吃饭了,再去调用Student里的方法,这就叫做动态代理

动态代理,可以侵入式的给代码增加额外的功能。

那程序为什么需要代理?代理长什么样?将一个小故事,一个关于鸡哥的小故事(我不是小黑子哦)。鸡哥是一个大明星,他会唱歌、跳舞,在程序中反映出来就是唱歌和跳舞两个方法。鸡哥是一个大明星,唱歌跳舞肯定不能随便,得先准备话筒和场地,准备话筒收钱以及准备场地收钱。那这两个新增功能是写在自己的方法中吗?想一下鸡哥是一个大明星,他自己做这两件事烦不烦,就把这两件事交个中介公司,公司会派一个代理人打理这些事

唱歌(){
  	
	真正开始唱歌;
}

跳舞(){
  	
	真正开始跳舞;
}
代理{
	准备话筒,收钱;
  	准备场地,收钱;
}

所以为什么程序需要代理?就是因为对象如果嫌身上干的事太多的话,可以通过代理来转移部分职责。那这个代理长什么样呢?就是说这个代理里面能写什么方法,肯定是有唱歌和跳舞的方法,因为其他人找鸡哥都是要先找代理。但是代理肯定不会唱跳,而是你找我唱歌,那我先收你钱,然后再调用鸡哥的唱歌方法,让唱。

说白了代理长什么样子,其实是和对象差不多的。对象有什么方法想被代理,代理就一定要有对应的方法,只不过代理要把准备工作先做完,然后再去调用对象中的方法。那代理如何能知道鸡哥要代理唱歌和跳舞这两个方法呢?万一还有第三个打篮球呢?代码中通过接口搞定,事先定义一个接口,有唱歌和跳舞的方法,这个接口中所有的方法就是我们想代理的方法。左边的代理和右边的鸡哥都要实现接口才可以。

public class BigStar implements Star {
    private String name;


    public BigStar() {
    }

    public BigStar(String name) {
        this.name = name;
    }

    //唱歌
    @Override
    public String sing(String name){
        System.out.println(this.name + "正在唱" + name);
        return "谢谢";
    }

    //跳舞
    @Override
    public void dance(){
        System.out.println(this.name + "正在跳舞");
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return "BigStar{name = " + name + "}";
    }
}
public interface Star {

    //我们可以把所有想要被代理的方法定义在接口当中

    //唱歌
    public abstract String sing(String name);
    //跳舞
    public abstract void dance();
}

如何为java对象创建一个代理对象呢?

  • java.lang.reflect.Proxy类:提供了为对象产生代理对象的方法:
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
//参数一:用于指定用哪个类加载器,去加载生成的代理类
//什么是类加载器呢?就是Java在运行的时候,需要有一个人把字节码文件加载到内存当中,就是类加载器去加载的
//参数二:指定接口,这些接口用于指定生成的代理长什么样,也就是有哪些方法
//参数三:用来指定生成的代理对象要干什么事情

/*
	类的作用:创建一个代理
*/
public class ProxyUtil {
  	/*
		方法的作用:
			给一个明星的对象,创建一个代理
		形参:
			被代理的明星对象
		返回值:
			给明星创建的代理
			
		需求:
     外面的人想要大明星唱一首歌
     1. 获取代理的对象
        代理对象 = ProxyUtil.createProxy(大明星的对象);
     2. 再调用代理的唱歌方法 底层会调用代理类中的invoke()
        代理对象.唱歌的方法("只因你太美");
	*/
  	public static Star createProxy(BigStar bigStar){
	  	Star star = (Star)Proxy.newProxyInstance(
		  		//参数一:用于指定用哪个类加载器,去加载生成的代理类
		  		ProxyUtil.class.getClassLoader(),
		  		//参数二:指定接口,这些接口用于指定生成的代理长什么样,也就是有哪些方法
				new Class[]{Star.class},
				//参数三:用来指定生成的代理对象要干什么事情
                new InvocationHandler() {
                  	@Override
                  	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
							  /*
							  * 参数一:代理的对象
							  * 参数二:要运行的方法 sing
							  * 参数三:调用sing方法时,传递的实参
							  * */
							  if("sing".equals(method.getName())){
								  System.out.println("准备话筒,收钱");
							  }else if("dance".equals(method.getName())){
								  System.out.println("准备场地,收钱");
							  }
							  //去找大明星开始唱歌或者跳舞
							  //代码的表现形式:调用大明星里面唱歌或者跳舞的方法
					  		  //反射的知识
							  return method.invoke(bigStar,args);
						  }
					  }
				);
	  

创建代理对象并执行方法的过程有些复杂,下面这个图能帮助理解,一个过程图。

总结

最后我们来总结一下代理,要掌握如下几点:

  1. 为什么需要代理?
  2. 代理可以无侵入式的给对象增加其他的功能
  3. 代理长什么样?
  4. 代理里面就是对象要被代理的方法
  5. java通过什么来保证代理的样子?
  6. 通过接口保证,对象和代理需要实现同一个接口,接口中就是被代理的所有方法
#你觉得今年春招回暖了吗##牛客在线求职答疑中心##牛客解忧铺##23届找工作求助阵地#
java基础知识 文章被收录于专栏

我是一个转码的小白,平时会在牛客中做选择题,在做题中遇到不会的内容就会去找视频或者文章学习,以此不断积累知识。这个专栏主要是记录一些我通过做题所学到的基础知识,希望能对大家有帮助

全部评论
讲的通俗易懂,感谢大佬分享
1 回复 分享
发布于 2023-03-13 20:57 广东
是不是相当于硬件中的中断呢??
点赞 回复 分享
发布于 2023-03-13 20:12 山西

相关推荐

2024-12-03 09:59
北京邮电大学 Java
点赞 评论 收藏
分享
评论
30
11
分享
牛客网
牛客企业服务