关于JAVA代理机制的理解和实现
代理机制
java常用的设计模式就有代理模式,代理机制是通过代理类和委托类实现相同的接口来完成代理过程,在这其中代理类主要是负责预处理、转发消息给委托类,以及处理消息等功能。代理类和委托类之间实现间接关联的关系,代理类不是真正的实现委托类的功能,只是作为一个桥梁的作用,通过代理类来间接实现委托类的功能,并且在这期间代理类可以添加更多的功能。
静态代理
静态代理是直接将代理的具体类、实现方法表现在代码里,在编译时就已经将接口,被代理类,代理类等确定下来。在程序运行之前,代理类的.class文件就已经生成。具体实现需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类.
实现共同的接口:
//基本接口
public interface IPersonDao {
void update();
}
目标对象:
ublic class PersonDao implements IPersonDao{
public void update() {
// TODO Auto-generated method stub
System.out.println("update方法");
}
}
代理类:
public class PersonDaoProxy implements IPersonDao{
private IPersonDao target;
public PersonDaoProxy(IPersonDao target){
this.target = target;
}
@Override
public void update() {
System.out.println("update前记录日志");
this.target.update();
System.out.println("update后记录日志");
}
}
测试类:
public class App {
public static void main(String[] args){
PersonDao p = new PersonDao();
PersonDaoProxy pProxy = new PersonDaoProxy(p);
pProxy.update();
}
}
输出:
update前记录日志
update方法
update后记录日志
动态代理
在代码运行期间加载被代理的类这就是动态代理,Spring AOP机制就是动态代理机制。
1.代理对象,不需要实现接口
2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
3.动态代理也叫做:JDK代理,接口代理
同样共同接口:
public interface Person {
//上交班费
void giveMoney();
}
委托类:
public class Student implements Person {
private String name;
public Student(String name) {
this.name = name;
}
@Override
public void giveMoney() {
try {
//间隔时间
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + "交50元");
}
}
工具类:
public class MonitorUtil {
private static ThreadLocal<Long> tl = new ThreadLocal<>();
public static void start() {
tl.set(System.currentTimeMillis());
}
//结束时打印耗时
public static void finish(String methodName) {
long finishTime = System.currentTimeMillis();
System.out.println(methodName + "方法耗时" + (finishTime - tl.get()) + "ms");
}
}
代理类:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class StuInvocationHandler<T> implements InvocationHandler {
//invocationHandler持有的被代理对象
T target;
public StuInvocationHandler(T target) {
this.target = target;
}
/**
* proxy:代表动态代理对象
* method:代表正在执行的方法
* args:代表调用目标方法时传入的实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理执行" +method.getName() + "方法");
//代理过程中插入监测方法,计算该方法耗时
MonitorUtil.start();
Object result = method.invoke(target, args);
MonitorUtil.finish(method.getName());
return result;
}
}
测试类:
public class ProxyTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建一个实例对象,这个对象是被代理的对象
Person zhangsan = new Student("张三");
//创建一个与代理对象相关联的InvocationHandler
InvocationHandler stuHandler = new StuInvocationHandler<Person>(zhangsan);
//创建一个代理对象stuProxy来代理zhangsan,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
Person stuProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler);
//代理执行交班费的方法
stuProxy.giveMoney();
}
}
输出:
代理执行giveMoney方法
张三上交班费50元
giveMoney方法耗时1009ms
以上文章参考于://https://www.cnblogs.com/gonjan-blog/p/6685611.html