代理到底是什么?

代理分类

  1. 静态代理
  2. 动态搭理

静态代理

我们先说静态代理的实现方式,为什么不推荐使用静态代理?
1.继承方式实现代理(静态代理中的继承代理)
  1. //目标对象
  2. publicclassUserImpl{
  3. publicvoid system(){
  4. System.out.println(“输出测试”);
  5. }
  6. }
  7. //代理对象
  8. publicclassProxyextendsUserImpl{
  9. @Override
  10. publicvoid system(){
  11. super.system();
  12. System.out.println(“增强之后的输出”);
  13. }
  14. }
  15. //测试类
  16. publicclassTestMain{
  17. publicstaticvoid main(String[] args){
  18. UserImpl user =newProxy();
  19. user.system();
  20. }
  21. }
静态代理可以看出来一点问题吧?
每次代理都要实现一个类,导致项目中代码很多;你每次想要代理,都要去实现一个类,代码就会成堆的增加,然后你就会发现项目的类就会越来越多,就会导致你们的项目显得很臃肿。而且代码的复用性太低了,并且耦合度非常高,这个我们所说的高内聚低耦合是相悖的。

动态代理

我们在看一下这个动态代理:
  1. //接口类
  2. publicinterfaceItalk{
  3. publicvoid talk(String msg);
  4. }
  5. //实现类
  6. publicclassPeopleimplementsItalk{
  7. publicString username;
  8. publicString age;
  9. publicString getName(){
  10. return username;
  11. }
  12. publicvoid setName(String name){
  13. this.username= name;
  14. }
  15. publicString getAge(){
  16. return age;
  17. }
  18. publicvoid setAge(String age){
  19. this.age = age;
  20. }
  21. publicPeople(String name1,String age1){
  22. this.username= name1;
  23. this.age = age1;
  24. }
  25. publicvoid talk(String msg){
  26. System.out.println(msg+”!你好,我是”+username+”,我年龄是”+age);
  27. }
  28. }
  29. //代理类
  30. publicclassTalkProxyimplementsItalk{
  31. Italk talker;
  32. publicTalkProxy(Italk talker){
  33. //super();
  34. this.talker=talker;
  35. }
  36. publicvoid talk(String msg){
  37. talker.talk(msg);
  38. }
  39. publicvoid talk(String msg,String singname){
  40. talker.talk(msg);
  41. sing(singname);
  42. }
  43. privatevoid sing(String singname){
  44. System.out.println(“唱歌:”+singname);
  45. }
  46. }
  47. //测试
  48. publicclassMyProxyTest{
  49. //代理模式
  50. publicstaticvoid main(String[] args){
  51. //不需要执行额外方法的
  52. Italk people1=newPeople(“湖海散人”,”18″);
  53. people1.talk(“No ProXY Test”);
  54. System.out.println(“—————————–“);
  55. //需要执行额外方法的
  56. TalkProxy talker=newTalkProxy(people1);
  57. talker.talk(“ProXY Test”,”七里香”);
  58. }
  59. }
上面代码解析
一个 Italk 接口,有空的方法 talk()(说话),所有的 people 对象都实现(implements)这个接口,实现 talk() 方法,前端有很多地方都将 people 实例化,执行 talk 方法,后来发现这些前端里有一些除了要说话以外还要唱歌(sing),那么我们既不能在 Italk 接口里增加 sing() 方法,又不能在每个前端都增加 sing 方法,我们只有增加一个代理类 talkProxy ,这个代理类里实现 talk 和 sing 方法,然后在需要 sing 方法的客户端调用代理类即可,
这也是实现动态代理的方式,是通过实现(implements)的方式来实现的,这种方法的优点,在编码时,代理逻辑与业务逻辑互相独立,各不影响,没有侵入,没有耦合。

cgLib代理

还有一种是cgLib的代理,这种代理则是适合那些没有接口抽象的类代理,而Java 动态代理适合于那些有接口抽象的类代理。
我们来通过代码了解一下他到底是怎么玩的。
  1. //我们实现一个业务类,不实现任何的接口
  2. /**
  3. * 业务类,
  4. */
  5. publicclassTestService{
  6. publicTestService(){
  7. System.out.println(“TestService的构造”);
  8. }
  9. /**
  10. * 该方法不能被子类覆盖,Cglib是无法代理final修饰的方法的
  11. */
  12. finalpublicString sayOthers(String name){
  13. System.out.println(“TestService:sayOthers>>”+name);
  14. returnnull;
  15. }
  16. publicvoid sayHello(){
  17. System.out.println(“TestService:sayHello”);
  18. }
  19. }
  20. /**
  21. * 自定义MethodInterceptor
  22. */
  23. publicclassMethodInterceptorTestimplementsMethodInterceptor{
  24. @Override
  25. publicObject intercept(Object o,Method method,Object[] objects,MethodProxy methodProxy)throwsThrowable{
  26. System.out.println(“======插入前置通知======”);
  27. Objectobject= methodProxy.invokeSuper(o, objects);
  28. System.out.println(“======插入后者通知======”);
  29. returnobject;
  30. }
  31. }
  32. /**
  33. * 测试
  34. */
  35. publicclassClient{
  36. publicstaticvoid main(String[] args){
  37. // 代理类class文件存入本地磁盘方便我们反编译查看源码
  38. System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,”D:\code”);
  39. // 通过CGLIB动态代理获取代理对象的过程
  40. Enhancer enhancer =newEnhancer();
  41. // 设置enhancer对象的父类
  42. enhancer.setSuperclass(TestService.class);
  43. // 设置enhancer的回调对象
  44. MethodInterceptorTest t =newMethodInterceptorTest();
  45. enhancer.setCallback(t);
  46. // 创建代理对象
  47. TestService proxy=(TestService)enhancer.create();
  48. // 通过代理对象调用目标方法
  49. proxy.sayHello();
  50. }
  51. }
  52. 上面代码想要运行,需要cglib的jar和asm的jar不要忘记找
运行结果
  1. CGLIB debugging enabled, writing to ‘D:code’
  2. TestService的构造
  3. ======插入前置通知======
  4. TestService:sayHello
  5. ======插入后者通知======
实现CGLIB动态代理必须实现MethodInterceptor(方法拦截器)接口,
这个接口只有一个intercept()方法,这个方法有4个参数:
  • obj表示增强的对象,即实现这个接口类的一个对象;
  • method表示要被拦截的方法;
  • args表示要被拦截方法的参数;
  • proxy表示要触发父类的方法对象;

代理的使用

那么什么时候使用静态态代理,什么时候使用动态代理和cgLib代理呢?
一般情况静态代理是很少是用的,因为他对代码的复用性或者说是耦合度都非常不友好,不推荐使用。
如果目标对象至少实现了一个接口,那么就用JDK动态代理,所有由目标对象实现的接口将全部都被代理。
如果目标对象没有实现任何接口,就是个类,那么就用CGLIB代理。
本站所有文章均由网友分享,仅用于参考学习用,请勿直接转载,如有侵权,请联系网站客服删除相关文章。若由于商用引起版权纠纷,一切责任均由使用者承担
极客文库 » 代理到底是什么?

Leave a Reply

欢迎加入「极客文库」,成为原创作者从这里开始!

立即加入 了解更多