README.md 6.6 KB
Newer Older
Goldchenn's avatar
Goldchenn 已提交
1 2 3
## 代理模式

> 2023-04-09
Goldchenn's avatar
Goldchenn 已提交
4 5 6
> 源码地址: 
> 
> https://gitcode.net/qq_39339588/proxy.git
Goldchenn's avatar
Goldchenn 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310

### 一、静态代理

静态代理:代理类与被代理类实现相同的接口,代理类有被代理类的引用。

1. 定义公共接口

```java
package test;

/**
 * 公用接口
 */
public interface UserService {
    /**
     * 获取用户
     */
    void getUser();
}

```



2. 定义代理类,实现了UserService接口,并且有被代理类的实例。执行时,调用被代理类实例的getUser方法。

```java
package test;

/**
 * 代理类
 */
public class UserServiceProxy implements UserService {
    /**
     * 接口为成员属性
     */
    private UserService userService;

    public UserServiceProxy(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void getUser() {
        doBefore();
        userService.getUser();
        doAfter();
    }

    private void doAfter() {
        System.out.println("代理类结束执行");
    }

    private void doBefore() {
        System.out.println("代理类开始执行");
    }
}

```



3. 定义实现类01,执行真实的方法

```java
package test;

/**
 * 用户实现类
 */
public class UserServiceImpl01 implements UserService {

    @Override
    public void getUser() {
        //被代理类,这里执行真实的方法
        System.out.println("被代理类,这里执行真实的方法01");
    }
}
```



4. 定义实现类02,执行真实的方法

```java
package test;

/**
 * 用户实现类
 */
public class UserServiceImpl02 implements UserService {

    @Override
    public void getUser() {
        //被代理类,这里执行真实的方法
        System.out.println("被代理类,这里执行真实的方法02");
    }
}
```



5. 主函数测试,可以看到代理类的getUser()方法,代理了实现类01和02的方法。代理类实际上调用了被代理类的方法。

```java
package test;

/**
 * 主函数测试静态代理
 */
public class ProxyMain {
    public static void main(String[] args) {
        // 传入01,代理会执行01的方法
        UserService userImpl01 = new UserServiceImpl01();
        UserServiceProxy userServiceProxy = new UserServiceProxy(userImpl01);
        userServiceProxy.getUser();
        System.out.println();
        // 传入02,代理会执行02的方法
        UserService userImpl02 = new UserServiceImpl02();
        UserServiceProxy userServiceProxy2 = new UserServiceProxy(userImpl02);
        userServiceProxy2.getUser();


    }
}

```

打印输出:
```text
//  被代理类,这里执行真实的方法01
//  代理类结束执行
//  代理类开始执行
//  被代理类,这里执行真实的方法02
//  代理类结束执行
```


### 二、动态代理

动态代理是指在程序运行时动态地创建代理类。动态代理的使用方式主要分为两种:

一种是基于接口的代理,JDK动态代理,通过JDK自带的反射类来生成动态代理类;

另一种是基于类的代理,CGLIB动态代理,通过字节码处理来实现类代理。

#### JDK动态代理

动态生成代理类。基于接口的代理,通过JDK自带的反射类来生成动态代理类.实现InvocationHandler接口,并重新invoke()方法

```java
package test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 动态代理:基于接口的代理,通过JDK自带的反射类来生成动态代理类.
 * 实现InvocationHandler接口,并重新invoke()方法
 */
public class UserServiceProxyHandler implements InvocationHandler {
    private Object target;

    public UserServiceProxyHandler(Object target) {
        this.target = target;
    }

    /**
     * 通过Proxy动态生成代理类
     */
    public <T> T getProxy() {
        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("JDK proxy before");
        method.invoke(target,args);
        System.out.println("JDK proxy after");
        return null;
    }
}

```



测试

```java
package test;

/**
 * 动态代理测试handler
 */
public class ProxyHandlerMain {
    public static void main(String[] args) {
        //通过动态代理类生成UserService接口类型对象
        UserService userService = new UserServiceProxyHandler(
                new UserServiceImpl01()).getProxy();
        // 调用getUser方法
        userService.getUser();
    }
}
```

输出:
```text
//  JDK proxy before
//  被代理类,这里执行真实的方法01
//  JDK proxy after
```




#### CGLIB动态代理

如果是maven工程,记着添加cglib依赖

```xml
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm -->
<dependency>
    <groupId>org.ow2.asm</groupId>
    <artifactId>asm</artifactId>
    <version>9.4</version>
</dependency>
```

如果是Java基础工程,记着把cglib和asm的jar包添加到library中

 ![image-20230409182347734](images/image-20230409182347734.png)



实现MethodIntercepptor类,并重新intercept()方法

```java
package test;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * CGLIB 动态代理,实现MethodInterceptor,重写intercept()方法
 */
public class UserServiceProxyInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("Cglib before");
        methodProxy.invokeSuper(o,objects);
        System.out.println("Cglib after");
        return null;
    }
}


```

main方法执行测试

```java
package test;

import net.sf.cglib.proxy.Enhancer;

/**
 * Cglib动态代理
 */
public class ProxyInterceptorMain {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        // 设置父类
        enhancer.setSuperclass(UserServiceImpl01.class);
        // 设置拦截器
        enhancer.setCallback(new UserServiceProxyInterceptor());

        UserServiceImpl01 userServiceImpl01 = (UserServiceImpl01) enhancer.create();
        // 调用getUser()方法
        userServiceImpl01.getUser();

    }
}

```

打印结果:
```text
//  Cglib before
//  被代理类,这里执行真实的方法01
//  Cglib after
```