动态代理

 

1、代理模式的分类:

代理模式的定义:为其他对象提供一种代理,以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理分为“静态代理”和“动态代理”:静态代理需要我们自己创建代理对象(需要创建代理类),而动态代理的代理对象是自动生成的,我们不需要关心代理对象的生成过程。

2、代理模式中有“抽象角色(接口)”、“代理角色”、“真实角色”这三个角色,代理对象和真实对象都会去实现“抽象角色”这个接口,   也就是说代理模式是基于接口来实现的。

 

代码

//抽象角色 定义买鞋的方法
public interface Iproduct {
	public int product();
}

//真实角色 负责干活
public class LiNingFactory implements Iproduct{
	@Override//干活的方法
	public int product(){
		System.out.println("李宁工厂生产了一双鞋子....定价399");
		int price  = 399;
		return price;
	}
}

//代理角色 负责买鞋子
public class LiNingStore implements Iproduct{
	Iproduct iproduct;
	//把真实对象拿进来 因为后面要找真实对象生产鞋子
	public LiNingStore(Iproduct iproduct){
		this.iproduct = iproduct;
	}
	//不生产鞋子 只卖鞋子 鞋子从李宁工厂拿来就好
	@Override
	public int product() {
		int price = iproduct.product();
		System.out.println("买了一双"+price+"元的鞋子");
		return price;
	}
}

public class ProductTest {
	public static void main(String[] args) {
		//直接找真实对象那么就没有涉及到代理
		//Iproduct iproduct = new LiNingFactory();
		//iproduct.product();
		//真实对象不买鞋子 买鞋子只能找代理
		LiNingFactory liNingFactory = new LiNingFactory();
		Iproduct iproduct = new LiNingStore(liNingFactory);
		iproduct.product();
	}
}

 

//抽象角色  
public interface ITarget {

	public void show();
}

//真实角色 
public class Target implements ITarget{
	@Override
	public void show(){
		System.out.println("真实角色的show方法执行了");
	}
}

//代理角色
public class TargetProxy implements ITarget {
	private ITarget target; // 目标
	public TargetProxy(ITarget target) {
		this.target = target;
	}
	@Override
	public void show() {
		// 在代理中通过目标来调用真实行为
		// 1.例如判断是否有权限调用目标行为
		// 2.进行日志操作
		// 3.性能临近
		target.show();
	}
}


/**
 * Returns an instance of a proxy class for the specified interfaces
 * that dispatches method invocations to the specified invocation
 * handler.  This method is equivalent to:
 * <pre>
 *     Proxy.getProxyClass(loader, interfaces).getConstructor(new Class[] { InvocationHandler.class }).newInstance(new Object[] { handler });
 * </pre>
 * @param   loader the class loader to define the proxy class
 * @param   interfaces the list of interfaces for the proxy class
 *          to implement
 * @param   h the invocation handler to dispatch method invocations to
 * @return  a proxy instance with the specified invocation handler of a
 *          proxy class that is defined by the specified class loader
 *          and that implements the specified interfaces
 * public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
 */
//测试类
public class ProxyTest {
	//直接调用目标角色
	@Test
	public void test1(){
		ITarget target = new Target();
		target.show();
	}
	//通过代理对象调用目标角色
	@Test
	public void test2(){
		//1创建目标对象
		ITarget target = new Target();
		//2创建代理对象
		ITarget targetProxy = new TargetProxy(target);
		//3通过代理对象调用目标对象的方法
		targetProxy.show();
	}
	//使用JDK提供的Proxy类完成动态代理
	@Test
	public void test3(){
		//1.创建目标对象
		final Target target = new Target();
		System.out.println("1.创建目标对象");
		/*
		 *  获取类加载器:  目标对象.getClass().getClassLoader();
			接口类对象 :  目标对象.getClass().getInterfaces();      class[]
 				主要是用来获取目标类中所实现的所有的接口数组
   			InvocationHandler :  监听器    
				主要功能: 当代理类去调用目标对象中方法的时候,
				会先执行监听器中invoke方法, 通过invoke来执行目标对象中方法 
		 */
		//newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
		ClassLoader loader = target.getClass().getClassLoader();
		Class<?>[] interfaces = target.getClass().getInterfaces();
		//2.动态创建代理对象
		System.out.println("2.1动态创建代理对象开始");
		ITarget newProxyInstance = (ITarget)Proxy.newProxyInstance(loader, interfaces, new InvocationHandler(){

			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				//4执行监听器中invoke方法, 通过invoke来执行目标对象中方法
				System.out.println("4.执行监听器中invoke方法, 通过invoke来执行目标对象中方法");
				return method.invoke(target, args);
			}
			
		});
		System.out.println("2.2动态创建代理对象结束");
		//3.代理对象调用目标对象中的方法
		System.out.println("3.代理对象调用目标对象中的方法");
		newProxyInstance.show();
		System.out.println("程序结束");
	}
}

执行结果:

1.创建目标对象

2.1动态创建代理对象开始

2.2动态创建代理对象结束

3.代理对象调用目标对象中的方法

4.执行监听器中invoke方法, 通过invoke来执行目标对象中方法

真实角色的show方法执行了

程序结束

 

1、newProxyInstance()详解

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

获取类加载器:  目标对象.getClass().getClassLoader();

接口类对象 :  目标对象.getClass().getInterfaces();      class[]

             主要是用来获取目标类中所实现的所有的接口数组

InvocationHandler :  监听器   

主要功能: 当代理类去调用目标对象中方法的时候, 会先执行监听器中invoke方法, 通过invoke来执行目标对象中方法

  1. 案例-动态代理完成性能监控
//案例-动态代理完成性能监控

//抽象角色
public interface IUserService {
	public String addUser(String userName,String passWord);
}


//目标角色
public class UserServiceimpl implements IUserService{

	@Override
	public String addUser(String userName, String passWord) {
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("添加用户:  用户名 "+userName+" 密码 "+passWord);
		return "hello "+userName;
	}
}

public class UserServiceTest {
	public static void main(String[] args) {
		//1创建目标对象
		IUserService userServiceimpl = new UserServiceimpl();
		//2创建代理对象
		ProxyUtils proxyUtils = new ProxyUtils(userServiceimpl);
		IUserService proxy = (IUserService)proxyUtils.getProxy();
		//3执行方法
		String addUser = proxy.addUser("tom", "123");
		System.out.println(addUser);
	}
}

/**
 * 代理对象工具类

Object invoke(Object proxy,Method method,Object[] args)throws Throwable
	在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。 
参数:
	proxy - 在其上调用方法的代理实例
	method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,
		          该接口可以是代理类赖以继承方法的代理接口的超接口。
	args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。
		      基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。 
返回:
	从代理实例的方法调用返回的值。如果接口方法的声明返回类型是基本类型,
	则此方法返回的值一定是相应基本包装对象类的实例;
	否则,它一定是可分配到声明返回类型的类型。
	如果此方法返回的值为 null 并且接口方法的返回类型是基本类型,
	则代理实例上的方法调用将抛出 NullPointerException。
	否则,如果此方法返回的值与上述接口方法的声明返回类型不兼容,
	则代理实例上的方法调用将抛出 ClassCastException。
 */
public class ProxyUtils implements InvocationHandler{
	//成员变量目标对象
	private Object target;
	public ProxyUtils(Object target){
		this.target = target;
	}
	//成员方法获得代理对象

	public Object getProxy(){
		ClassLoader loader = target.getClass().getClassLoader();
		Class<?>[] interfaces = target.getClass().getInterfaces();
		return Proxy.newProxyInstance(loader, interfaces, this);
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// 在调用前,得到一个时间
		long start = System.currentTimeMillis();
		Object invoke = method.invoke(target, args);
		// 在调用后,得到一个时间
		long end = System.currentTimeMillis();
		long time = end - start;
		System.out.println(time);
		return invoke;
	}
	/*	
	public Object getProxy(){
		ClassLoader loader = target.getClass().getClassLoader();
		Class<?>[] interfaces = target.getClass().getInterfaces();
		return Proxy.newProxyInstance(loader, interfaces, new InvocationHandler(){

			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				System.out.println(method.getName());
				System.out.println(args[0]+" "+args[1]);
				return method.invoke(target, args);
			}
			
		});
	}
	*/
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值