代理:代替某人做一些事情
这里引申出几个属于 委托人、被委托人
通俗说就是 我要找刘德华打广告,我不能直接找上他本人,我要先找他的代理人才行。
为什么不能找上他本人呢?
因为代理可以为他过滤掉一些收益不高或者公司实力不雄厚的广告业务,也就是说代理存在的意义是在真正做某件事前,先做一些事前准备。
Java中有两种代理实现方式 静态代理、动态代理
静态代理:
静态代理实际上就是声明一个和被代理类具有同样方法签名的类,把被代理类实例作为代理类的成员,这样在调用代理类方法,先执行代理类的操作,然后执行被代理类的方法。
被代理类 ,明星能够 拍电影和唱歌
public class Star {
public void movie() {
System.out.println("拍电影......");
}
public void sing() {
System.out.println("唱歌......");
}
}
代理类 (StarProxy) 代理明星(Star)承接 拍电影和唱歌的业务
public class StarProxy {
private Star _star;
public StarProxy(Star star) {
this._star=star;
}
public void movie() {
System.out.println("代理......前");
_star.movie();
System.out.println("代理......后");
}
public void sing() {
System.out.println("代理......前");
_star.sing();
System.out.println("代理......后");
}
}
在执行代理方法时,在代理方法内部会调用被真正代理类的方法。
public class JMain {
public static void main(String[] args) {
StarProxy proxy=new StarProxy(new Star());
proxy.movie(); //拍电影
proxy.sing();//唱歌
}
}
动态代理:
动态的为类生成一个代理类,和静态代理最大的不同之处在于,它发生在运行时,不需要单独编写代理类。
在包 java.lang.reflect 下有动态代理的相关实现
这里我们关注两个类型
Proxy和 InvocationHandler
Proxy 根据指定的被代理类class和接口动态生成代理对象
InvocationHandler 代理类实现的接口,当调用被代理类任何方法时,会执行接口Invoke方法。
public static void main(String[] args){
Star star=new Star();
IStar starproxy=(IStar) Proxy.newProxyInstance(Star.class.getClassLoader(),Star.class.getInterfaces(),new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理------前");
Object ret= method.invoke(star, args);
System.out.println("代理------后");
return ret;
}
});
starproxy.movie();
}
这里没有预先定义代理类,而是在运行时动态生成的,其底层原理是通过反射来实现,java内置的动态代理 需要被代理类实现一个接口,因此有一定的局限性。
这里介绍另一种实现动态代理的优秀框架 cglib,它采用asm动态织入的方式,在内存中动态生成代理类字节码。
public class JMain {
public static void main(String[] args) {
StarProxy starProxy = new JMain().new StarProxy();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Star.class);
enhancer.setCallback(starProxy);
Star o = (Star)enhancer.create();
o.movie();
}
/***
* 定义一个代理类,实现方法拦截器接口
* @author RWX
*
*/
class StarProxy implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("代理调用方法前:" + methodProxy.getSuperName());
Object o1 = methodProxy.invokeSuper(o, args);
System.out.println("代理调用方法后: " + methodProxy.getSuperName());
return o1;
}
}