以服务于中国广大创业者为己任,立志于做最好的创业网站。

标签云创业博客联系我们

导航菜单

我想做免费代理,代理商是做什么的

面试前,星球的高尔夫球手问了我一些问题,说,让我写下代理人,区别于代理人的依据是什么,应该用在哪里?在这篇文章中,我将详细解释一些关于代理的问题。

代理分类

:静态代理动态管理

静态代理

:先说静态代理的实现。为什么不建议使用静态代理?

1.实现代理的继承方式(静态代理中的继承代理)

//目标对象公共类user impl { public void system(){ system。out . println(' output test ');} }//proxy object public class proxy扩展用户impl { @ override public void system(){ super。system();System.out.println('增强后输出');} }//test class public class test main { public static void main(string[]args){ user impl user=new proxy();user . system();}}静态代理能看出一点问题吗?

每次代理都要实现一个类,导致项目中代码很多;每次要代理,都要实现一个类,代码会成堆增加。然后你会发现项目中的类会越来越多,会让你的项目看起来臃肿不堪。而且代码的复用性太低,耦合度很高,和我们所说的高内聚低耦合是背道而驰的。

动态代理

我们正在关注这个动态代理:

//接口类public interface talk { public void talk(string msg);}//实现类public class people实现它{ public string username公共字符串时代;公共字符串getName() {返回用户名;} public void SetName(String name){ this . username=name;} public String GetAge(){ return age;} public void Setage(String age){ this . age=age;}公众人物(字符串名称1,字符串年龄1){ this . username=name 1;

this.age = age1; } public void talk(String msg) { System.out.println(msg+"!你好,我是"+username+",我年龄是"+age); } } //代理类 public class TalkProxy implements Italk { Italk talker; public TalkProxy (Italk talker) { //super(); this.talker=talker; } public void talk(String msg) { talker.talk(msg); } public void talk(String msg,String singname) { talker.talk(msg); sing(singname); } private void sing(String singname){ System.out.println("唱歌:"+singname); } } //测试 public class MyProxyTest { //代理模式 public static void main(String[] args) { //不需要执行额外方法的 Italk people1=new People("湖海散人","18"); people1.talk("No ProXY Test"); System.out.println("-----------------------------"); //需要执行额外方法的 TalkProxy talker=new TalkProxy(people1); talker.talk("ProXY Test","七里香"); } }

上面代码解析


一个 Italk 接口,有空的方法 talk()(说话),所有的 people 对象都实现(implements)这个接口,实现 talk() 方法,前端有很多地方都将 people 实例化,执行 talk 方法,后来发现这些前端里有一些除了要说话以外还要唱歌(sing),那么我们既不能在 Italk 接口里增加 sing() 方法,又不能在每个前端都增加 sing 方法,我们只有增加一个代理类 talkProxy ,这个代理类里实现 talk 和 sing 方法,然后在需要 sing 方法的客户端调用代理类即可,


这也是实现动态代理的方式,是通过实现(implements)的方式来实现的,这种方法的优点,在编码时,代理逻辑与业务逻辑互相独立,各不影响,没有侵入,没有耦合。


cgLib代理

还有一种是cgLib的代理,这种代理则是适合那些没有接口抽象的类代理,而Java 动态代理适合于那些有接口抽象的类代理。


我们来通过代码了解一下他到底是怎么玩的。




//我们实现一个业务类,不实现任何的接口 /** * 业务类, */ public class TestService { public TestService() { System.out.println("TestService的构造"); } /** * 该方法不能被子类覆盖,Cglib是无法代理final修饰的方法的 */ final public String sayOthers(String name) { System.out.println("TestService:sayOthers>>"+name); return null; } public void sayHello() { System.out.println("TestService:sayHello"); } }/** * 自定义MethodInterceptor */public class MethodInterceptorTest implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("======插入前置通知======"); Object object = methodProxy.invokeSuper(o, objects); System.out.println("======插入后者通知======"); return object; }} /** * 测试 */ public class Client { public static void main(String[] args) { // 代理类class文件存入本地磁盘方便我们反编译查看源码 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:code"); // 通过CGLIB动态代理获取代理对象的过程 Enhancer enhancer = new Enhancer(); // 设置enhancer对象的父类 enhancer.setSuperclass(TestService.class); // 设置enhancer的回调对象 MethodInterceptorTest t = new MethodInterceptorTest(); enhancer.setCallback(t); // 创建代理对象 TestService proxy= (TestService)enhancer.create(); // 通过代理对象调用目标方法 proxy.sayHello(); } }上面代码想要运行,需要cglib的jar和asm的jar不要忘记找

运行结果




CGLIB debugging enabled, writing to 'D:code'TestService的构造======插入前置通知======TestService:sayHello======插入后者通知======

实现CGLIB动态代理必须实现MethodInterceptor(方法拦截器)接口,


这个接口只有一个intercept()方法,这个方法有4个参数:


  • obj表示增强的对象,即实现这个接口类的一个对象;
  • method表示要被拦截的方法;
  • args表示要被拦截方法的参数;
  • proxy表示要触发父类的方法对象;

代理的使用

那么什么时候使用静态态代理,什么时候使用动态代理和cgLib代理呢?


一般情况静态代理是很少是用的,因为他对代码的复用性或者说是耦合度都非常不友好,不推荐使用。


如果目标对象至少实现了一个接口,那么就用JDK动态代理,所有由目标对象实现的接口将全部都被代理。


如果目标对象没有实现任何接口,就是个类,那么就用CGLIB代理。