java代理技术的学习以及分析

当我们说道代理的时候脑海里出现的是代理模式,没错,这是比较专业的说法。代理模式的实现形式可以分为:静态代理和动态代理两种。根据技术又有jdk代理,cglib代理两种。下面我就根据自己浅薄的学习说一下代理。

代理:根据汉语的意思就是:代替他人进行相应的操作,我们想要找一个明星唱歌,那么我就要找他的经纪人,然后经纪人再找明星,经纪人所做的作用就是代理。那么这就很明白了,代理分为代理类(经纪人),委托类(明星),代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。而主要的逻辑是委托类实现的。

从上面的话语我们就知道代理模式的好处:

  1.   代理对象的价值就是帮助委托类进行拦截,事前处理,事后善后,保护委托类的隐私,拦截对委托类的真实访问
  2.   代理类应该跟委托类具有相同的功能,或者代理类会根据用户传过来的信息进行处理,然后决定调用委托类的方法

说了这么多想必大家就问了,代理技术都是要运行在哪些地方呢?其实java的代理技术是一个很重要的技术,在很多地方都有运行到,比如springAOP技术。运行的场景就更多啦:预处理消息、过滤消息等功能。

说了这么多下面开始说代理的实现:

        静态代理:所谓的静态代理就是在程序运行前,代理类的class文件已经存在,是静态的,不是在程序运行过程中,根据信息而动态创建的,

    静态代理组成部分有三种:公共的接口,代理类,委托类

接口:

        

package com.fg.proxy;

/**
 * @version 1.0
 * @filename ISubject
 * @author fg
 * @date 2018-06-08
 * @describe 测试静态代理,接口声明
 * @history 2018-06-08 1.0
 */

public interface ISubject {
	/**
	 * @version 1.0
	 * @methodName doSomething
	 * @author: wyf
	 * @date 2018-06-09
	 * @describe 定义代理接口方法
	 * @history 2018-06-09 定义
	 */
	public void doSomething();
}

委托类:实现真正的逻辑

package com.fg.proxy.impl;

import java.util.concurrent.ThreadPoolExecutor;

import com.fg.proxy.ISubject;

/**
 * @version 1.0
 * @filename RealSubjectImpl
 * @author fg
 * @date 2018-06-08
 * @describe 静态代理接口实现类,测试静态代理服务
 * @history 2018-06-08 1.0
 */

public class RealSubjectImpl implements ISubject {

	/**
	 * @version 1.0
	 * @methodName doSomething
	 * @author: wyf
	 * @date 2018-06-09
	 * @describe 实现代理方法代理接口方法
	 * @history 2018-06-09 定义
	 */
	@Override
	public void doSomething() {
		try {
			Thread.sleep(1000);
			System.out.println("暂停1000ms,重新开始跑");
		} catch (InterruptedException e) {
			System.out.println(e.toString());
		}

	}

}

代理类:实现同样的接口,包含一个委托类的私有对象,在相同的方法中加入必要的处理逻辑,然后调用委托类对象真正的逻辑接口。代理服务因为不知道真正的逻辑实现逻辑是多久,一般会打印委托类运行时间

package com.fg.proxy.impl;

import com.fg.proxy.ISubject;

/**
 * @version 1.0
 * @filename ProxySubjectImpl
 * @author wyf
 * @date 2018-06-08
 * @describe 测试静态代理,接口声明
 * @history 2018-06-08 1.0
 */
public class ProxySubjectImpl implements ISubject {

	private ISubject subject;

	/*
	 * @version 1.0
	 * 
	 * @author FG
	 * 
	 * @methodName ProxySubjectImpl
	 * 
	 * @params sub 委托类
	 * 
	 * @description 构造,初始化委托类
	 * 
	 * @history:2018-06-09 创建
	 */
	public ProxySubjectImpl(ISubject sub) {
		this.subject = sub;
	}

	/*
	 * @version 1.0
	 * 
	 * @author FG
	 * 
	 * @methodName ProxySubjectImpl
	 * 
	 * @params sub 委托类
	 * 
	 * @return void
	 * 
	 * @description 构造,实现接口函数,调用委托类的功能进行
	 * 
	 * @history:2018-06-09 创建
	 */
	@Override
	public void doSomething() {
		long l_startTime = System.currentTimeMillis();
		this.subject.doSomething();
		long l_endTime = System.currentTimeMillis();
		System.out.println("程序运行时间: " + (l_endTime - l_startTime) + "ms");
	}

	/*
	 * @version 1.0
	 * 
	 * @author FG
	 * 
	 * @methodName doSleep1000ms
	 * 
	 * @params
	 * 
	 * @return void
	 * 
	 * @description 延迟1000ms
	 * 
	 * @history:2018-06-09 创建
	 */
	public void doSleep1000ms() {

		long l_startTime = System.currentTimeMillis();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			System.out.println("延迟失败,原因:" + e.toString());

		}
		long l_endTime = System.currentTimeMillis();
		System.out.println("程序运行时间:" + (l_endTime - l_startTime) + "ms");

	}

}

到现在我们就完成了一个简单的静态代理实现,那么就可以写一个main函数调用。

public class ProxyMain {
	/*
	 * @version 1.0
	 * 
	 * @author FG
	 * 
	 * @methodName main
	 * 
	 * @params 
	 * 
	 * @description 方法入口函数
	 * 
	 * @history:2018-06-09. 创建
	 */
	public static void main(String agrs[]) {
		
		ISubject  proxySub = ProxySubjectFactory.getInstanceProxy();
		proxySub.doSomething();
		
     }
}

动态代理:

            动态代理接口

package com.fg.proxy;
/**
 * @version 1.0
 * @filename IDynamicProxy
 * @author wyf
 * @date 2018-06-09
 * @describe 动态代理接口
 * @history 2018-06-09 1.0
 */
public interface IDynamicProxy {
	/*
	 * @version 1.0
	 * 
	 * @author FG
	 * 
	 * @methodName singSong
	 * 
	 * @params musicCode 
	 * 
	 * @return void 
	 * 
	 * @description  唱8
	 * 
	 * @history:2018-06-09 创建
	 */
		public  void singSong(String musicCode);
		/*
		 * @version 1.0
		 * 
		 * @author FG
		 * 
		 * @methodName danceDj
		 * 
		 * @params dancerStr
		 * 
		 * @return void 
		 * 
		 * @description  跳舞
		 * 
		 * @history:2018-06-09 创建
		 */
	
		public void  danceDj(String dancerStr);
}

动态代理委托类实现:

package com.fg.proxy.impl;

import com.fg.proxy.IDynamicProxy;

/**
 * @version 1.0
 * @filename DynamicProxyImpl
 * @author wyf
 * @date 2018-06-09
 * @describe 实现动态代理
 * @history 2018-06-09 1.0
 */
public class DynamicProxyImpl implements IDynamicProxy {

	/*
	 * @version 1.0
	 * 
	 * @author FG
	 * 
	 * @methodName singSong
	 * 
	 * @params musicCode 
	 * 
	 * @return void 
	 * 
	 * @description  唱8
	 * 
	 * @history:2018-06-09 创建
	 */
	@Override
	public void singSong(String musicCode) {
		try {
			System.out.println("所唱歌曲:"+musicCode);
			Thread.sleep(1000);
			System.out.println("唱歌结束!");
		} catch (InterruptedException e) {
			System.out.println("唱歌时候报错");
		}

	}

	
	/*
	 * @version 1.0
	 * 
	 * @author FG
	 * 
	 * @methodName danceDj
	 * 
	 * @params dancerStr
	 * 
	 * @return void 
	 * 
	 * @description  跳舞
	 * 
	 * @history:2018-06-09 创建
	 */
	@Override
	public void danceDj(String dancerStr) {
		System.out.println("所跳舞蹈:"+dancerStr);
		try {
			Thread.sleep(1000);
			System.out.println("跳舞结束!");
		} catch (InterruptedException e) {

			System.out.println("唱歌报错!"+e.toString());
		}
	}

}

动态代理实现需要运用java的java.lang.reflect.proxy类和实现接口java.lang.reflect.InvocationHandler

实现接口InvocationHandler:

package com.fg.proxy.impl;

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

import com.fg.util.MutilUtil;

/**
 * @version 1.0
 * @filename DynamicProxyInvocationHanlder
 * @author FG
 * @date 2018-06-11
 * @describe 实现InvocationHanlder接口,动态实现
 * @history 2018-06-11 1.0
 */
public class DynamicProxyInvocationHanlder<T> implements InvocationHandler {
	// 委托类的实例
	private T targer;

	/*
	 * @version 1.0
	 * 
	 * @author FG
	 * 
	 * @methodName DynamicProxyInvocationHanlder
	 * 
	 * @params
	 * 
	 * @return void
	 * 
	 * @description 构造函数,初始化委托类的实例
	 * 
	 * @history:2018-06-11 创建
	 */
	public DynamicProxyInvocationHanlder(T t_targer) {

		this.targer = t_targer;
	}

	/*
	 * @version 1.0
	 * 
	 * @author FG
	 * 
	 * @methodName invoke
	 * 
	 * @params proxy 动态代理对象,method 动态调用的方法,arg2 调用委托类的参数数组
	 * 
	 * @return Object 返回
	 * 
	 * @description 动态调用方法
	 * 
	 * @history:2018-06-11 创建
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] arg2) throws Throwable {
		System.out.println("代理执行" + method.getName() + "方法");
		MutilUtil.startTime();
		Object result = method.invoke(targer, arg2);
		MutilUtil.endTime();

		return result;
	}

}

       工具类: 

package com.fg.util;

/**
 * @version 1.0
 * @filename MutilUtil
 * @author FG
 * @date 2018-06-11
 * @describe 综合工具类
 * @history 2018-06-11 1.0
 */
public class MutilUtil {
	private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();

	/*
	 * @version 1.0
	 * 
	 * @author FG
	 * 
	 * @methodName startTime
	 * 
	 * @params
	 * 
	 * @return void
	 * 
	 * @description 运行到当前的时间
	 * 
	 * @history:2018-06-11 创建
	 */
	public static void startTime() {
		threadLocal.set(System.currentTimeMillis());
		System.out.println("开始时间:"+threadLocal.get()+"ms" );

	}

	/*
	 * @version 1.0
	 * 
	 * @author FG
	 * 
	 * @methodName endTime
	 * 
	 * @params
	 * 
	 * @return void
	 * 
	 * @description 结束时间
	 * 
	 * @history:2018-06-11 创建
	 */
	public static void endTime() {
		Long l_endTime = System.currentTimeMillis();
		System.out.println("程序运行耗时:"+ (l_endTime - threadLocal.get())+"ms");

	}
}

实现调用动态代理类:

                IDynamicProxy  dynamicProxy = new DynamicProxyImpl();
		
		DynamicProxyInvocationHanlder<IDynamicProxy> dynProxyHandler = new DynamicProxyInvocationHanlder<IDynamicProxy>(dynamicProxy);
		IDynamicProxy LDHProxy =(IDynamicProxy) Proxy.newProxyInstance(IDynamicProxy.class.getClassLoader(), new Class<?>[] {IDynamicProxy.class}, dynProxyHandler);
		LDHProxy.singSong("wangyafei");
		LDHProxy.danceDj("xiaotiane");
到现在动态代理就实现了,刚开始学习的时候我有一个疑问,proxy类调用的机制是什么?通过查询很多资料我才知道原来proxy在调用newProxyInstance函数的时候指定了类的加载器,类的接口,然后根据Invocationhanlder,返回去一个代理类对象,每一次调用代理对象的方法的时候,都会调用Invocationhanlderi的invoke函数,根据函数名和参数调用委托类的同名方法。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值