动态代理(Proxy)

动态代理是一门java技术 是面向切面编程的重要技术,面向切面编程可以理解为面向方法编程,
比如如果要统计每个方法花费的时间,如果在每个方法中都都加入该测量方法,在一个工程中该工作量太大了,可以通过动态代理来实现。
对于动态代理黑马程序员给了一个很好的例子就是,你如果找一个明星唱歌你不可能直接找到她本人,你需要首先找到该明星的代理人然后把准备工作都做完 再找到明星唱歌。准备工作是代理人做的事情,唱歌这件事情是明星自己做的。回到第一段的例子,如果要测量每个方法的花费时间,可以让每个方法有一个代理人实现测量方法,然后方法体本身自己实现自身的方法。

动态代理的实现步骤
1.先创建一个接口 令被代理类实现

package com.itheima.ProxyDemo;
/*
 * 实现动态代理的接口
 * */
public interface Star {
	//@Param("name") 唱的歌曲名称
	void sing(String Sangname);
	//返回值String
	String dance();
}

2.创建一个实例类来实现接口 并重写接口的方法

package com.itheima.ProxyDemo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/*
* 明星类
* */
@Data@AllArgsConstructor
@NoArgsConstructor
public class StarImpl implements Star{
	private String name;

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

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

 3.创建一个代理工具类(工具类代码解释都在注释中)

package com.itheima.ProxyDemo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/*
* 实现动态代理的工具类
* */
public class ProxyUtils {
	//方法定义为static 类可以直接调用
	public static Object getProxyInstance(Object target) {
		/*java.lang.reflect.Proxy中静态方法newProxyInstance的签名
		public static Object newProxyInstance(
				ClassLoader loader,
				Class<?>[] interfaces,
				InvocationHandler h)
		第一个参数 ClassLoader loader 类加载器 用来加载代理类的加载 一般使用当前类加载器即可
		第二个参数 Class<?>[] interfaces target实现的接口列表  (.getClass)
		 	一般使用target反射来获得target的类加载器 然后获得该类实现的接口列表 (.getInterfaces)
		第三个参数 InvocationHandler h 是一个接口 通过匿名内部类来实现 详细功能 下面聊		*/
		Object o = Proxy.newProxyInstance(
				target.getClass().getClassLoader(),
				target.getClass().getInterfaces(),
				new InvocationHandler() {
					/*
					 * 该匿名类需要重写一个invoke方法
					 * invoke方法有三个参数Object proxy, Method method, Object[] args
					 * 第一个参数proxy是代理对象,一般不用
					 * 第二个参数method是目前正在执行的方法
					 * 		一般使用method.getName()来获取目前正在执行方法的名称
					 * 		一般使用method.invoke(target,args)来调用该方法的真正执行
					 * 第三个参数args是传入method的参数
					 * */
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						String name = method.getName();
						/*
						 * 此处写出代理人需要做的工作 以代理人实现喊话功能为例
						 * */
						System.out.println("代理人正在喊话" + name);
						/*
						利用反射的invoke来调用真正方法 该方法的返回值为一个Object
						* 该方法真正执行
						* 第一个参数 target是正在执行的方法所属的对象
						* 第二个参数 args是正在执行的方法传入的参数
						* 该
						* */
						Object invoke = method.invoke(target, args);
						return invoke;
					}
				}
		);
		return o ; //将该代理人返回
	}
}

  4.在测试类中声明一个实体类,然后通过代理工具类来声明代理 最后通过代理调用方法

package com.itheima;

import com.itheima.ProxyDemo.ProxyUtils;
import com.itheima.ProxyDemo.Star;
import com.itheima.ProxyDemo.StarImpl;
import org.junit.jupiter.api.Test;

public class TestProxy {

	@Test
	public void testProxy(){
		Star star = new StarImpl("张学友"); // 真实对象
		Star proxyInstance = (Star)ProxyUtils.getProxyInstance(star);// 代理对象
		proxyInstance.sing("冰雨");
		System.out.println(proxyInstance.dance());
	}
}

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值