Java代理(Proxy)

一、代理的概念

  动态代理技术是整个java技术中最重要的一个技术,它是学习java框架的基础,不会动态代理技术,那么在学习Spring这些框架时是学不明白的。

  动态代理技术就是用来产生一个对象的代理对象的。在开发中为什么需要为一个对象产生代理对象呢?
  举一个现实生活中的例子:歌星或者明星都有一个自己的经纪人,这个经纪人就是他们的代理人,当我们需要找明星表演时,不能直接找到该明星,只能是找明星的代理人。比如刘德华在现实生活中非常有名,会唱歌,会跳舞,会拍戏,刘德华在没有出名之前,我们可以直接找他唱歌,跳舞,拍戏,刘德华出名之后,他干的第一件事就是找一个经纪人,这个经纪人就是刘德华的代理人(代理),当我们需要找刘德华表演时,不能直接找到刘德华了(刘德华说,你找我代理人商谈具体事宜吧!),只能是找刘德华的代理人,因此刘德华这个代理人存在的价值就是拦截我们对刘德华的直接访问!
  这个现实中的例子和我们在开发中是一样的,我们在开发中之所以要产生一个对象的代理对象,主要用于拦截对真实业务对象的访问。那么代理对象应该具有什么方法呢?代理对象应该具有和目标对象相同的方法

  所以在这里明确代理对象的两个概念:
    1、代理对象存在的价值主要用于拦截对真实业务对象的访问
    2、代理对象应该具有和目标对象(真实业务对象)相同的方法。刘德华(真实业务对象)会唱歌,会跳舞,会拍戏,我们现在不能直接找他唱歌,跳舞,拍戏了,只能找他的代理人(代理对象)唱歌,跳舞,拍戏,一个人要想成为刘德华的代理人,那么他必须具有和刘德华一样的行为(会唱歌,会跳舞,会拍戏),刘德华有什么方法,他(代理人)就要有什么方法,我们找刘德华的代理人唱歌,跳舞,拍戏,但是代理人不是真的懂得唱歌,跳舞,拍戏的,真正懂得唱歌,跳舞,拍戏的是刘德华,在现实中的例子就是我们要找刘德华唱歌,跳舞,拍戏,那么只能先找他的经纪人,交钱给他的经纪人,然后经纪人再让刘德华去唱歌,跳舞,拍戏。

二、java中的代理

2.1、"java.lang.reflect.Proxy"类介绍

  现在要生成某一个对象的代理对象,这个代理对象通常也要编写一个类来生成,所以首先要编写用于生成代理对象的类。在java中如何用程序去生成一个对象的代理对象呢,java在JDK1.5之后提供了一个"java.lang.reflect.Proxy"类,通过"Proxy"类提供的一个newProxyInstance方法用来创建一个对象的代理对象,如下所示:

1 static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

  newProxyInstance方法用来返回一个代理对象,这个方法总共有3个参数,ClassLoader loader用来指明生成代理对象使用哪个类装载器,Class<?>[] interfaces用来指明生成哪个对象的代理对象,通过接口指定,InvocationHandler h用来指明产生的这个代理对象要做什么事情。所以我们只需要调用newProxyInstance方法就可以得到某一个对象的代理对象了。

2.2、编写生成代理对象的类

  在java中规定,要想产生一个对象的代理对象,那么这个对象必须要有一个接口,所以我们第一步就是设计这个对象的接口,在接口中定义这个对象所具有的行为(方法)

  1、定义对象的行为接口

 1 package cn.gacl.proxy;
 2
 3 /**
 4 * @ClassName: Person
 5 * @Description: 定义对象的行为
 6 * @author: 孤傲苍狼
 7 * @date: 2014-9-14 下午9:44:22
 8 *
 9 */
10 public interface Person {
11
12     /**
13     * @Method: sing
14     * @Description: 唱歌
15     * @Anthor:孤傲苍狼
16     *
17     * @param name
18     * @return
19     */
20     String sing(String name);
21     /**
22     * @Method: sing
23     * @Description: 跳舞
24     * @Anthor:孤傲苍狼
25     *
26     * @param name
27     * @return
28     */
29     String dance(String name);
30 }

  2、定义目标业务对象类

 1 package cn.gacl.proxy;
 2
 3 /**
 4 * @ClassName: LiuDeHua
 5 * @Description: 刘德华实现Person接口,那么刘德华会唱歌和跳舞了
 6 * @author: 孤傲苍狼
 7 * @date: 2014-9-14 下午9:22:24
 8 *
 9 */
10 public class LiuDeHua implements Person {
11
12     public String sing(String name){
13         System.out.println("刘德华唱"+name+"歌!!");
14         return "歌唱完了,谢谢大家!";
15     }
16
17     public String dance(String name){
18         System.out.println("刘德华跳"+name+"舞!!");
19         return "舞跳完了,多谢各位观众!";
20     }
21 }

  3、创建生成代理对象的代理类

 1 package cn.gacl.proxy;
 2
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 import java.lang.reflect.Proxy;
 6
 7 /**
 8 * @ClassName: LiuDeHuaProxy
 9 * @Description: 这个代理类负责生成刘德华的代理人
10 * @author: 孤傲苍狼
11 * @date: 2014-9-14 下午9:50:02
12 *
13 */
14 public class LiuDeHuaProxy {
15
16     //设计一个类变量记住代理类要代理的目标对象
17     private Person ldh = new LiuDeHua();
18
19     /**
20     * 设计一个方法生成代理对象
21     * @Method: getProxy
22     * @Description: 这个方法返回刘德华的代理对象:Person person = LiuDeHuaProxy.getProxy();//得到一个代理对象
23     * @Anthor:孤傲苍狼
24     *
25     * @return 某个对象的代理对象
26     */
27     public Person getProxy() {
28         //使用Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)返回某个对象的代理对象
29         return (Person) Proxy.newProxyInstance(LiuDeHuaProxy.class
30                 .getClassLoader(), ldh.getClass().getInterfaces(),
31                 new InvocationHandler() {
32                     /**
33                      * InvocationHandler接口只定义了一个invoke方法,因此对于这样的接口,我们不用单独去定义一个类来实现该接口,
34                      * 而是直接使用一个匿名内部类来实现该接口,new InvocationHandler() {}就是针对InvocationHandler接口的匿名实现类
35                      */
36                     /**
37                      * 在invoke方法编码指定返回的代理对象干的工作
38                      * proxy : 把代理对象自己传递进来
39                      * method:把代理对象当前调用的方法传递进来
40                      * args:把方法参数传递进来
41                      *
42                      * 当调用代理对象的person.sing("冰雨");或者 person.dance("江南style");方法时,
43                      * 实际上执行的都是invoke方法里面的代码,
44                      * 因此我们可以在invoke方法中使用method.getName()就可以知道当前调用的是代理对象的哪个方法
45                      */
46                     @Override
47                     public Object invoke(Object proxy, Method method,
48                             Object[] args) throws Throwable {
49                         //如果调用的是代理对象的sing方法
50                         if (method.getName().equals("sing")) {
51                             System.out.println("我是他的经纪人,要找他唱歌得先给十万块钱!!");
52                             //已经给钱了,经纪人自己不会唱歌,就只能找刘德华去唱歌!
53                             return method.invoke(ldh, args); //代理对象调用真实目标对象的sing方法去处理用户请求
54                         }
55                         //如果调用的是代理对象的dance方法
56                         if (method.getName().equals("dance")) {
57                             System.out.println("我是他的经纪人,要找他跳舞得先给二十万块钱!!");
58                             //已经给钱了,经纪人自己不会唱歌,就只能找刘德华去跳舞!
59                             return method.invoke(ldh, args);//代理对象调用真实目标对象的dance方法去处理用户请求
60                         }
61
62                         return null;
63                     }
64                 });
65     }
66 }

  测试代码:

 1 package cn.gacl.proxy;
 2
 3 public class ProxyTest {
 4
 5     public static void main(String[] args) {
 6
 7         LiuDeHuaProxy proxy = new LiuDeHuaProxy();
 8         //获得代理对象
 9         Person p = proxy.getProxy();
10         //调用代理对象的sing方法
11         String retValue = p.sing("冰雨");
12         System.out.println(retValue);
13         //调用代理对象的dance方法
14         String value = p.dance("江南style");
15         System.out.println(value);
16     }
17 }

  运行结果如下:

  
  Proxy类负责创建代理对象时,如果指定了handler(处理器),那么不管用户调用代理对象的什么方法,该方法都是调用处理器的invoke方法。
  由于invoke方法被调用需要三个参数:代理对象、方法、方法的参数,因此不管代理对象哪个方法调用处理器的invoke方法,都必须把自己所在的对象、自己(调用invoke方法的方法)、方法的参数传递进来。

三、动态代理应用

  在动态代理技术里,由于不管用户调用代理对象的什么方法,都是调用开发人员编写的处理器的invoke方法(这相当于invoke方法拦截到了代理对象的方法调用)。并且,开发人员通过invoke方法的参数,还可以在拦截的同时,知道用户调用的是什么方法,因此利用这两个特性,就可以实现一些特殊需求,例如:拦截用户的访问请求,以检查用户是否有访问权限、动态为某个对象添加额外的功能。

3.1、在字符过滤器中使用动态代理解决中文乱码

  在平时的JavaWeb项目开发中,我们一般会写一个CharacterEncodingFilter(字符过滤器)来解决整个JavaWeb应用的中文乱码问题,如下所示:

 1 package me.gacl.web.filter;
 2
 3 import java.io.IOException;
 4
 5 import javax.servlet.Filter;
 6 import javax.servlet.FilterChain;
 7 import javax.servlet.FilterConfig;
 8 import javax.servlet.ServletException;
 9 import javax.servlet.ServletRequest;
10 import javax.servlet.ServletResponse;
11
12 /**
13 * @ClassName: CharacterEncodingFilter
14 * @Description: 解决中文乱码的字符过滤器
15 * @author: 孤傲苍狼
16 * @date: 2014-9-14 下午10:38:12
17 *
18 */
19 public class CharacterEncodingFilter implements Filter {
20
21     @Override
22     public void init(FilterConfig filterConfig) throws ServletException {
23
24     }
25
26     @Override
27     public void doFilter(ServletRequest request, ServletResponse response,
28             FilterChain chain) throws IOException, ServletException {
29         //解决以Post方式提交的中文乱码问题
30         request.setCharacterEncoding("UTF-8");
31         response.setCharacterEncoding("UTF-8");
32         response.setContentType("text/html;charset=UTF-8");
33         chain.doFilter(request, response);
34     }
35
36     @Override
37     public void destroy() {
38
39     }
40 }

  但是这种写法是没有办法解决以get方式提交中文参数时的乱码问题的,我们可以用如下的代码来证明上述的解决中文乱码过滤器只对以post方式提交中文参数时有效,而对于以get方式提交中文参数时无效

  jsp测试页面如下:

 1 <%@ page language="java" pageEncoding="UTF-8"%>
 2 <%--引入jstl标签库 --%>
 3 <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
 4 <!DOCTYPE HTML>
 5 <html>
 6   <head>
 7     <title>使用字符过滤器解决解决get、post请求方式下的中文乱码问题</title>
 8   </head>
 9   <body>
10        <%--使用c:url标签构建url,构建好的url存储在servletDemo1变量中--%>
11        <c:url value="/servlet/ServletDemo1" scope="page" var="servletDemo1">
12            <%--构建的url的附带的中文参数 ,参数名是:username,值是:孤傲苍狼--%>
13            <c:param name="username" value="孤傲苍狼"></c:param>
14        </c:url>
15       <%--使用get的方式访问 --%>
16        <a href="${servletDemo1}">超链接(get方式请求)</a>
17        <hr/>
18        <%--使用post方式提交表单 --%>
19        <form action="${pageContext.request.contextPath}/servlet/ServletDemo1" method="post">
20            用户名:<input type="text" name="username" value="孤傲苍狼" />
21            <input type="submit" value="post方式提交">
22        </form>
23
24   </body>
25 </html>

  处理请求的ServletDemo1代码如下:

 1 package me.gacl.web.controller;
 2
 3 import java.io.IOException;
 4 import java.io.PrintWriter;
 5
 6 import javax.servlet.ServletException;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10
11 public class ServletDemo1 extends HttpServlet {
12
13     public void doGet(HttpServletRequest request, HttpServletResponse response)
14             throws ServletException, IOException {
15         // 接收参数
16         String username = request.getParameter("username");
17         // 获取请求方式
18         String method = request.getMethod();
19         // 获取输出流
20         PrintWriter out = response.getWriter();
21         out.write("请求的方式:" + method);
22         out.write("<br/>");
23         out.write("接收到的参数:" + username);
24     }
25
26     public void doPost(HttpServletRequest request, HttpServletResponse response)
27             throws ServletException, IOException {
28         doGet(request, response);
29     }
30 }

  在web.xml中注册上述的CharacterEncodingFilter和ServletDemo1

 1  <filter>
 2       <filter-name>CharacterEncodingFilter</filter-name>
 3       <filter-class>me.gacl.web.filter.CharacterEncodingFilter</filter-class>
 4   </filter>
 5
 6   <filter-mapping>
 7       <filter-name>CharacterEncodingFilter</filter-name>
 8       <url-pattern>/*</url-pattern>
 9   </filter-mapping>
10
11   <servlet>
12     <servlet-name>ServletDemo1</servlet-name>
13     <servlet-class>me.gacl.web.controller.ServletDemo1</servlet-class>
14   </servlet>
15
16   <servlet-mapping>
17     <servlet-name>ServletDemo1</servlet-name>
18     <url-pattern>/servlet/ServletDemo1</url-pattern>
19   </servlet-mapping>    

  测试结果如下所示:

  

  从运行结果可以看出,上述的过滤器的确是不能解决以get方式提交中文参数的乱码问题,下面使用动态代理技术改造上述的过滤器,使之能够解决以get方式提交中文参数的乱码问题,改造后的过滤器代码如下:

 1 package me.gacl.web.filter;
 2
 3 import java.io.IOException;
 4 import java.lang.reflect.InvocationHandler;
 5 import java.lang.reflect.Method;
 6 import java.lang.reflect.Proxy;
 7
 8 import javax.servlet.Filter;
 9 import javax.servlet.FilterChain;
10 import javax.servlet.FilterConfig;
11 import javax.servlet.ServletException;
12 import javax.servlet.ServletRequest;
13 import javax.servlet.ServletResponse;
14 import javax.servlet.http.HttpServletRequest;
15 import javax.servlet.http.HttpServletResponse;
16
17 /**
18 * @ClassName: CharacterEncodingFilter
19 * @Description: 解决中文乱码的字符过滤器
20 * @author: 孤傲苍狼
21 * @date: 2014-9-14 下午10:38:12
22 *
23 */
24 public class CharacterEncodingFilter implements Filter {
25
26     @Override
27     public void init(FilterConfig filterConfig) throws ServletException {
28
29     }
30
31     @Override
32     public void doFilter(ServletRequest req, ServletResponse resp,
33             FilterChain chain) throws IOException, ServletException {
34
35         final HttpServletRequest request = (HttpServletRequest) req;
36         HttpServletResponse response = (HttpServletResponse) resp;
37         //解决以Post方式提交的中文乱码问题
38         request.setCharacterEncoding("UTF-8");
39         response.setCharacterEncoding("UTF-8");
40         response.setContentType("text/html;charset=UTF-8");
41         //获取获取HttpServletRequest对象的代理对象
42         ServletRequest requestProxy = getHttpServletRequestProxy(request);
43         /**
44          * 传入代理对象requestProxy给doFilter方法,
45          * 这样用户在使用request对象时实际上使用的是HttpServletRequest对象的代理对象requestProxy
46          */
47         chain.doFilter(requestProxy, response);
48     }
49
50
51     /**
52     * @Method: getHttpServletRequestProxy
53     * @Description: 获取HttpServletRequest对象的代理对象
54     * @Anthor:孤傲苍狼
55     *
56     * @param request
57     * @return HttpServletRequest对象的代理对象
58     */
59     private ServletRequest getHttpServletRequestProxy(final HttpServletRequest request){
60         ServletRequest proxy  = (ServletRequest) Proxy.newProxyInstance(
61                 CharacterEncodingFilter.class.getClassLoader(),
62                 request.getClass().getInterfaces(),
63                 new InvocationHandler(){
64                     @Override
65                     public Object invoke(Object proxy, Method method, Object[] args)
66                             throws Throwable {
67                         //如果请求方式是get并且调用的是getParameter方法
68                         if (request.getMethod().equalsIgnoreCase("get") && method.getName().equals("getParameter")) {
69                             //调用getParameter方法获取参数的值
70                             String value = (String) method.invoke(request, args);
71                             if(value==null){
72                                 return null;
73                             }
74                             //解决以get方式提交的中文乱码问题
75                             return new String(value.getBytes("iso8859-1"),"UTF-8");
76                         }else {
77                             //直接调用相应的方法进行处理
78                             return method.invoke(request, args);
79                         }
80                     }
81                 });
82         //返回HttpServletRequest对象的代理对象
83         return proxy;
84     }
85
86     @Override
87     public void destroy() {
88
89     }
90 }

  我们在过滤器中使用动态代理技术生成一个HttpServletRequest对象的代理对象requestProxy,然后把代理对象requestProxy进行chain.doFilter(requestProxy, response)传递给用户使用,这样用户实际上使用的就是HttpServletRequest对象的代理对象requestProxy。然而这一过程对于用户来说是透明的,用户是不知道自己使用的HttpServletRequest对象是一个代理对象requestProxy,由于代理对象requestProxy和目标对象HttpServletRequest具有相同的方法,当用户调用getParameter方法接收中文参数时,实际上调用的就是代理对象requestProxy的invoke方法,因此我们就可以在invoke方法中就判断当前的请求方式以及用户正在调用的方法,如果判断当前的请求方式是get方式并且用户正在调用的是getParameter方法,那么我们就可以手动处理get方式提交中文参数的中文乱码问题了。

  测试结果如下所示:

  

3.2、在字符过滤器中使用动态代理压缩服务器响应的内容后再输出到客户端

  压缩过滤器的代码如下:

  1 package me.gacl.web.filter;
  2
  3 import java.io.ByteArrayOutputStream;
  4 import java.io.IOException;
  5 import java.io.OutputStreamWriter;
  6 import java.io.PrintWriter;
  7 import java.lang.reflect.InvocationHandler;
  8 import java.lang.reflect.Method;
  9 import java.lang.reflect.Proxy;
 10 import java.util.zip.GZIPOutputStream;
 11
 12 import javax.servlet.Filter;
 13 import javax.servlet.FilterChain;
 14 import javax.servlet.FilterConfig;
 15 import javax.servlet.ServletException;
 16 import javax.servlet.ServletOutputStream;
 17 import javax.servlet.ServletRequest;
 18 import javax.servlet.ServletResponse;
 19 import javax.servlet.http.HttpServletRequest;
 20 import javax.servlet.http.HttpServletResponse;
 21
 22 /**
 23 * @ClassName: GzipFilter
 24 * @Description: 压缩过滤器,将web应用中的文本都经过压缩后再输出到浏览器
 25 * @author: 孤傲苍狼
 26 * @date: 2014-9-15 下午9:35:36
 27 *
 28 */
 29 public class GzipFilter implements Filter {
 30
 31     @Override
 32     public void init(FilterConfig filterConfig) throws ServletException {
 33
 34     }
 35
 36     @Override
 37     public void doFilter(ServletRequest req, ServletResponse resp,
 38             FilterChain chain) throws IOException, ServletException {
 39
 40         final HttpServletRequest request = (HttpServletRequest) req;
 41         final HttpServletResponse response = (HttpServletResponse) resp;
 42         final ByteArrayOutputStream bout = new ByteArrayOutputStream();
 43         final PrintWriter pw = new PrintWriter(new OutputStreamWriter(bout,"UTF-8"));
 44
 45         chain.doFilter(request, getHttpServletResponseProxy(response, bout, pw));
 46         pw.close();
 47         //拿到目标资源的输出
 48         byte result[] = bout.toByteArray();
 49         System.out.println("原始大小:" + result.length);
 50
 51         ByteArrayOutputStream bout2 = new ByteArrayOutputStream();
 52         GZIPOutputStream gout = new GZIPOutputStream(bout2);
 53         gout.write(result);
 54         gout.close();
 55
 56         //拿到目标资源输出的压缩数据
 57         byte gzip[] = bout2.toByteArray();
 58         System.out.println("压缩大小:" + gzip.length);
 59
 60         response.setHeader("content-encoding", "gzip");
 61         response.setContentLength(gzip.length);
 62         response.getOutputStream().write(gzip);
 63     }
 64
 65     /**
 66     * @Method: getHttpServletResponseProxy
 67     * @Description: 获取HttpServletResponse对象的代理对象
 68     * @Anthor:孤傲苍狼
 69     *
 70     * @param response
 71     * @param bout
 72     * @param pw
 73     * @return HttpServletResponse对象的代理对象
 74     */
 75     private ServletResponse getHttpServletResponseProxy(
 76             final HttpServletResponse response,
 77             final ByteArrayOutputStream bout,
 78             final PrintWriter pw) {
 79
 80         return (ServletResponse) Proxy.newProxyInstance(GzipFilter.class.getClassLoader(),
 81                 response.getClass().getInterfaces(),
 82                 new InvocationHandler(){
 83                     @Override
 84                     public Object invoke(Object proxy, Method method, Object[] args)
 85                             throws Throwable {
 86                         if(method.getName().equals("getWriter")){
 87                             return pw;
 88                         }else if(method.getName().equals("getOutputStream")){
 89                             return new MyServletOutputStream(bout);
 90                         }else{
 91                             return method.invoke(response, args);
 92                         }
 93                     }
 94                 });
 95     }
 96
 97     @Override
 98     public void destroy() {
 99
100     }
101
102     class MyServletOutputStream extends ServletOutputStream{
103
104         private ByteArrayOutputStream  bout = null;
105         public MyServletOutputStream(ByteArrayOutputStream  bout){
106             this.bout = bout;
107         }
108         @Override
109         public void write(int b) throws IOException {
110             bout.write(b);
111         }
112
113     }
114 }

  在web.xml中注册上述的GzipFilter

 1  <filter>
 2       <description>配置压缩过滤器</description>
 3       <filter-name>GzipFilter</filter-name>
 4       <filter-class>me.gacl.web.filter.GzipFilter</filter-class>
 5   </filter>
 6
 7   <!--jsp文件的输出的内容都经过压缩过滤器压缩后才输出 -->
 8   <filter-mapping>
 9       <filter-name>GzipFilter</filter-name>
10       <url-pattern>*.jsp</url-pattern>
11       <!-- 配置过滤器的拦截方式-->
12       <!-- 对于在Servlet中通过
13           request.getRequestDispatcher("jsp页面路径").forward(request, response)
14       方式访问的Jsp页面的要进行拦截 -->
15       <dispatcher>FORWARD</dispatcher>
16       <!--对于直接以URL方式访问的jsp页面进行拦截,过滤器的拦截方式默认就是REQUEST-->
17       <dispatcher>REQUEST</dispatcher>
18   </filter-mapping>
19   <!--js文件的输出的内容都经过压缩过滤器压缩后才输出 -->
20   <filter-mapping>
21       <filter-name>GzipFilter</filter-name>
22       <url-pattern>*.js</url-pattern>
23   </filter-mapping>
24   <!--css文件的输出的内容都经过压缩过滤器压缩后才输出 -->
25   <filter-mapping>
26       <filter-name>GzipFilter</filter-name>
27       <url-pattern>*.css</url-pattern>
28   </filter-mapping>
29   <!--html文件的输出的内容都经过压缩过滤器压缩后才输出 -->
30   <filter-mapping>
31       <filter-name>GzipFilter</filter-name>
32       <url-pattern>*.html</url-pattern>
33   </filter-mapping>

  GzipFilter过滤器会将*.jsp,*.js,*.css,*.html这些文件里面的文本内容都经过压缩后再输出到客户端显示。

时间: 2024-10-14 11:09:17

Java代理(Proxy)的相关文章

java代理Proxy

首先是静态代理: 1 public class Test1 { 2 3 public static void main(String[] args) { 4 IA a = new APoxy(new A()); 5 a.doJob(); 6 } 7 8 } 9 //功能接口 10 interface IA{ 11 public void doJob(); 12 } 13 //委托类 14 class A implements IA{ 15 16 @Override 17 public void

Java 实现代理(Proxy)模式

/** * 游戏者接口 * @author stone * */ public interface IGamePlayer { // 登录游戏 public void login(String user, String password); // 杀怪,网络游戏的主要特色 public void killBoss(); // 升级 public void upgrade(); } /** * 游戏者 * @author stone * */ public class GamePlayer imp

Java代理设计模式(Proxy)的四种具体实现:静态代理和动态代理

面试问题:Java里的代理设计模式(Proxy Design Pattern)一共有几种实现方式?这个题目很像孔乙己问"茴香豆的茴字有哪几种写法?" 所谓代理模式,是指客户端(Client)并不直接调用实际的对象(下图右下角的RealSubject),而是通过调用代理(Proxy),来间接的调用实际的对象. 代理模式的使用场合,一般是由于客户端不想直接访问实际对象,或者访问实际的对象存在技术上的障碍,因而通过代理对象作为桥梁,来完成间接访问. 实现方式一:静态代理 开发一个接口IDev

java 代理模式详解

java 动态代理(JDK和cglib) 设计模式这东东每次看到就明白可过段时间又不能很流利的说出来,今天就用详细的比喻和实例来加深自己的理解(小弟水平不高有不对的地方希望大家能指出来). (1)代理这个词生活中有很多比如在街边卖手机卡.充公交地铁卡的小商店他们都起了代理的作用,java中的代理跟这些小店商的作用是一样的.再比如我想在淘宝上开个服装店但又没有货源怎么办,这时候我就要跟淘宝上某一卖家联系做他的代理.我跟我的商家都要卖衣服(就好比我们都继承了卖衣服的接口sellClothesInte

代理(Proxy)——对象结构型模式

代理模式的意图: 为其它对象提供代理,以控制对这个对象的访问.对一个对象进行访问控制的原因是为了我们在确实需要这个对象时才对它进行创建和初始化.有些对象创建的开销非常大,所以我们应该根据需要进行创建.Proxy则可以代替一个对象,并在需要时负责实例化这个对象.就像我们小学的时候总是欺负学习好的同学,让学习好的同学代替我们写作业,要不然我们放学就在路上堵着打他们,学习好的同学就乖乖的帮我们写作业,第二天到学校老师看了作业还表扬我们学习有进步呢.这就是一个很好的代理模式的例子. 代理模式的类图如下:

Java代理模式

Java代理模式分为静态代理和动态代理模式 静态代理模式比较简单,直接上图和代码: 代理模式类图如下: 在代理模式中的角色: ● 抽象对象角色:声明了目标对象和代理对象的共同接口,这样一来在任何可以使用目标对象的地方都可以使用代理对象. ● 目标对象角色:定义了代理对象所代表的目标对象. ● 代理对象角色:代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象:代理对象提供一个与目标对象相同的接口,以便可以在任何时候替代目标对象.代理对象通常在客户端调用传递给目标对象之前或之后,执行某个

java 代理的三种实现方式

Java 代理模式有如下几种实现方式: 1.静态代理. 2.JDK动态代理. 3.CGLIB动态代理. 示例,有一个打招呼的接口.分别有两个实现,说hello,和握手.代码如下. 接口: public interface Greeting { public void doGreet(); } 实现类: public class SayHello implements Greeting { @Override public void doGreet() { System.out.println("

java代理模式学习

Java动态代理模式 1. 代理:一个角色代表别一个角色来完成某些特定的功能. 比如:生产商,中间商,客户这三者这间的关系 客户买产品并不直接与生产商打交道,也不用知道产品是如何产生的,客户只与中间商打交道,而中间商就可以对产品进行一些包装,提供一些售后的服务. 代理模式有三个角色: 1. 抽象主题角色 2. 代理主题角色 3. 实际被代理角色 其它类通过访问代理主题角色来访问实际被代理角色. 2. 下面我们来个一个静态代理的实现. 我以一个坦克为例. 抽象主题角色:Moveable Java代

java代理机制简单实现

java代理分静态代理和动态代理,动态代理有jdk代理和cglib代理两种,在运行时生成新的子类class文件.本文主要练习下动态代理,代码用于备忘.对于代理的原理和机制,网上有很多写的很好的,就不班门弄斧了. jdk代理 Java代码下载    import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class Prox

Java 代理使用及代理原理

今天再测试Socket编程时,无法连接外网.公司用的是Http的代理.上网搜索也没看太懂,所以花了大量时间来学习.看了HTTP和TCP协议的关系好,才有所明白.现在能通过Socket使用HTTP代理了,结果很简单,过程却好难. 1. 先简要说说HTTP和TCP(具体内容自行Google,资料很多很全),这里就讲讲要点: HTTP:是应用层协议,是基于传输层协议的. TCP: 是传输层协议,是基于网络层协议的. IP: 是网络层协议. 一个TCP的连接要进行三次握手(就像转户口一样,不详说),HT