JDK 动态代理
这里记录一下自己对代理的理解,重点为JDK动态代理。首先要明确一件事情,代理这个词既可以是名字也可以是动词。要注意区分。名词时候,叫做代理商也许会更好一些。
代理的目的
为什么需要代理,我觉得更多的时候是为了实现对某一个切面的编程。比如,我们有一个动物类,在开发中,我们发现需要给动物类的子类进行一次扩展,这里我们可以使用继承。但是,如果是同时很多子类都需要这个方法,又不是所有的子类都需要。我们怎么做?这里我们就可以使用代理来实现扩展。对于需要扩展的子类,我们并不直接new出来,而是通过一个代理类生成,代理类中在原有的基础上进行了扩展,增加了新的方法。就像我们现在手里有很多树木,各种种类的树木。其中有很多珍贵的红木。这玩意当然自己出售放心。还有很多松木,杨木。这种便宜的东西出售时候我们就不用太在意了,找个委托商,我只要这些木头给我钱,至于你想怎么销售,卖给谁,买家希望做成什么样子。我都不再关心了。而这里的委托商,就是一个代理。我们把木头给他,至于做成桌子,椅子都无所谓了。这就是代理。
JAVA中代理的种类
在java中代理有三种。分别为静态代理,JDK动态代理,和CgLib代理。
静态代理
静态代理比较简单,就是通过建立一个代理类(与被代理的对象使用相同的接口),然后在代理类里通过组合的形式,把需要被代理的对象传入,重写的方法中调用被代理对象的方法即可实现。
静态代理demo
subject:
/**
* @author sunyan
* @description
*/
public interface Subject {
/**
*需要增强的方法
*/
void doSomeThing();
}
需要被代理的类
RealSubject
/**
* @author sunyan
* @description
*/
public class RealSubject implements Subject{
@Override
public void doSomeThing() {
System.out.println("我是需要被代理的对象");
}
}
代理商
/**
* @author sunyan
* @description
*/
public class Proxyer implements Subject{
private Subject subject;
public Proxyer(Subject subject) {
this.subject = subject;
}
@Override
public void doSomeThing() {
System.out.println("我代理了它,开始执行");
subject.doSomeThing();
System.out.println("代理处理完成");
}
}
到这里静态代理就结束了,只要调用Proxyer产生的对象里的doSomeThing()就可以对原对象方法进行增强。
JDK动态代理
对于上面的方法存在一个问题,如果买家说我需要一把铁做的椅子(卖木头的赚钱赚多了,行业扩展了),可我们接口却是木头,这就尴尬了,你不能说我只有木头的接口,没法生存椅子。怎么办?最好的方法就是把接口做成灵活的。这样就可以代理做任何材料的椅子了。在java中我们可以通过反射来实现这个功能。
我们只需要下面三个步骤就可以完成jdk动态代理
1.定义一个接口(当然这个接口无所谓啦,定义哪个都行)
2.定义一个代理商,这个代理商就很特别了,他需要实现InvocationHandler接口,并重写里面的invoke。这个接口里只存在一个方法。就是invoke。
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
3.第三步,我们要在代理商里(其他地方也行)调用Proxy.newProxyInstance()方法;通过读源码的注释可以发现
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
@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
,这里会返回一个代理对象,它使用loader加载器,实现一些特殊接口(特殊接口就是我们需要被代理对象的接口)
可能你会觉得很奇怪,在代理中没有调用invoke方法就可以实现增强的方法了。其实。。。。。我也不太懂,但是根据我的直觉,应该是我们调用方法的时候,那个.就是对invoke的调用。
具体代码如下:
Subject接口:
public interface Subject {
/**
*
*/
void doSomeThing();
}```
需要被代理的对象的类:
```java
public class RealSubject implements Subject {
@Override
public void doSomeThing() {
System.out.println("需要被代理的事务");
}
}
代理商
/**
* @author sunyan
* @description
*/
public class ProxyFactory implements InvocationHandler {
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
public <T> T getInstance(){
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置增强");
method.invoke(target);
return null;
}
}```
#### cglib动态代理
这个动态代理和上面的不太一样,它是基于父类继承,通过过滤器实现的,emm,具体的实现过程还没有好好观摩,等观摩好了再继续