代理模式:为其他对象提供一种代理以控制目标对象的访问,在某些情况下, 一个对象不适合或者不能直接引用另外一个对象,代理对象可以在这个客户类和目标对象中起到一个桥梁作用。

简单来说,代理对象的使用,是在不修改原有目标对象的基础上,增强原有目标对象的功能逻辑。

代理的实现有两种,静态代理和动态代理,而动态代理,又分为jdk动态代理和cglib动态代理。

本文目录:

  • 1.静态代理的实现
  • 2.jdk动态代理的实现
  • 3.cglib动态代理的实现

1.静态代理

需要目标类实现接口,代理类和目标类实现相同的接口,静态代理,是有代理类的,而动态代理是没有的。

1.1定义接口类UserService

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.java4all.test_proxy_static;

/**
* author:lightClouds917
* date:2018/10/7
* description:接口
*/
public interface UserService {

String doFirst();

void doSecond();
}

1.2定义接口类的实现类

也就是我们的目标类,我们需要增强的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.java4all.test_proxy_static;

/**
* author:lightClouds917
* date:2018/10/7
* description:接口实现类 目标类,等待增强
*/
public class UserServiceImpl implements UserService{
@Override
public String doFirst() {
System.out.println("执行了doFirst()方法");
return "iloveyou";
}

@Override
public void doSecond() {
System.out.println("执行了doSecond()方法");
}
}

1.3定义目标类的代理类

要和目标类实现相同的接口,在此代理类的方法中进行增强

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.java4all.test_proxy_static;

import org.springframework.stereotype.Service;

/**
* author:lightClouds917
* date:2018/10/7
* description:静态代理 有代理类
* 在代理类中增强目标类的方法
*/
@Service
public class UserServiceImplProxy implements UserService{

@Override
public String doFirst() {
//调用目标类的原始方法
UserServiceImpl userService = new UserServiceImpl();
String str = userService.doFirst();
//增强逻辑 这里以字母转换为例
str = str.toUpperCase();
return str;
}

@Override
public void doSecond() {
UserService userService = new UserServiceImpl();
userService.doSecond();
}
}

1.4测试

测试一下,原本目标类中有个方法是返回iloveyou,在代理类中,我们对此方法进行了增强,将字母转为了大写进行返回。

1
2
3
4
5
6
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
package com.java4all.test_proxy_static;

/**
* author:lightClouds917
* date:2018/10/7
* description:测试静态代理
*/
public class TestProxy {

public static void main(String[]args){
test1();
System.out.println("--------------");
test2();
}

/**
* 调用原有的目标对象来实现功能
*/
public static void test1(){
UserService userService = new UserServiceImpl();
System.out.println(userService.doFirst());
userService.doSecond();
}

/**
* 调用代理对象来实现功能
*/
public static void test2(){
UserService userServiceImplProxy = new UserServiceImplProxy();
System.out.println(userServiceImplProxy.doFirst());
userServiceImplProxy.doSecond();
}
}

测试结果如下:

1
2
3
4
5
6
7
执行了doFirst()方法
iloveyou
执行了doSecond()方法
--------------
执行了doFirst()方法
ILOVEYOU
执行了doSecond()方法

2.jdk动态代理

jdk动态代理的原理是,和目标类实现共同的接口,由Proxy.newProxyInstance生成一个代理对象,在代理对象调用方法时,在invoke方法中增强。

jdk动态代理,不需要代理类,他的实现必须是要求目标类实现了某个接口,然后代理对象和目标类实现了相同的接口。

2.1定义接口

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.java4all.test_proxy_jdk;

/**
* author:lightClouds917
* date:2018/10/7
* description:接口
*/
public interface UserService {

String doFirst();

void doSecond();
}

2.2定义实现类

也就是需要增强的目标类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.java4all.test_proxy_jdk;

/**
* author:lightClouds917
* date:2018/10/7
* description:接口实现类 目标类,等待增强
*/
public class UserServiceImpl implements UserService {
@Override
public String doFirst() {
System.out.println("执行了doFirst()方法");
return "iloveyou";
}

@Override
public void doSecond() {
System.out.println("执行了doSecond()方法");
}
}

2.3测试jdk动态代理

1
2
3
4
5
6
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
package com.java4all.test_proxy_jdk;

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

/**
* author:lightClouds917
* date:2018/10/7
* description:jdk动态代理
* 没有代理类
* 由Proxy.newProxyInstance生成一个代理对象,在调用方法时,在invoke方法中增强
* 要求:目标类存在接口,目标类和代理对象要实现相同的接口
*/
public class TestProxy {

public static void main(String[]args){
test1();
}

public static void test1(){
//目标类对象
UserService target = new UserServiceImpl();

/**jdk动态代理,没有代理类,由Proxy.newProxyInstance生成一个代理对象*/
UserService userService = (UserService)Proxy.newProxyInstance(
target.getClass().getClassLoader(),//目标类的类加载器
target.getClass().getInterfaces(), //目标类实现的所有接口
new InvocationHandler() { //匿名内部类

//proxy:代理对象
//method:目标方法
//args:目标方法参数列表
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = method.invoke(target, args);
if(invoke != null){
return invoke.toString().toUpperCase();
}
return null;
}
});
System.out.println(userService.doFirst());
userService.doSecond();
}

}

结果:

1
2
3
执行了doFirst()方法
ILOVEYOU
执行了doSecond()方法

3.cglib动态代理

cglib动态代理的原理是,生成目标类的子类,在子类中进行增强,这个子类对象就是代理对象。

使用cglib代理时,要求目标类必须可以被继承,即没有用final修饰。

CGLIB(code generation Library)是一个开源项目,是一个强大的,高性能的,高质量的代码生成类库。他可以在运行期间拓展和增强java类,Spring用它来实现AOP编程。

3.1目标类UserService

不需要实现接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.java4all.test_proxy_cglib;

/**
* author:lightClouds917
* date:2018/10/7
* description:目标类,没有实现接口,等待增强
*/
public class UserService {

public String doFirst() {
System.out.println("执行了doFirst()方法");
return "iloveyou";
}

public void doSecond() {
System.out.println("执行了doSecond()方法");
}
}

3.2代理工厂

用来生成目标类的代理对象,此类需要实现MethodInterceptor

1
2
3
4
5
6
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
package com.java4all.test_proxy_cglib;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
* author:lightClouds917
* date:2018/10/7
* description:返回目标类的代理对象
* 需要实现MethodInterceptor
*/
public class MyCglib implements MethodInterceptor{

private UserService target;

public MyCglib(UserService target) {
this.target = target;
}

/**
* 返回目标类的代理对象
* @return
*/
public UserService MyCglibCreator(){
Enhancer enhancer = new Enhancer();
//指定父类,即目标类 cglib原理:子类增强父类
enhancer.setSuperclass(UserService.class);
//设置回调接口 当前类继承了MethodInterceptor,
//此接口public interface MethodInterceptor extends Callback
enhancer.setCallback(this);
//create创建cglib动态代理对象
return (UserService)enhancer.create();
}


//回调接口的方法 代理对象执行目标方法时,会触发该方法
@Override
public Object intercept(Object o,
Method method,
Object[] objects,
MethodProxy methodProxy) throws Throwable {
Object invoke = method.invoke(target, objects);
if(invoke != null){
return invoke.toString().toUpperCase();
}
return invoke;
}
}

3.3测试cglib动态代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.java4all.test_proxy_cglib;


/**
* author:lightClouds917
* date:2018/10/7
* description:cglib动态代理
*/
public class TestProxy {

public static void main(String[]args){
test1();
}

public static void test1(){
UserService target = new UserService();

//调用工厂类获取代理对象
MyCglib myCglib = new MyCglib(target);
UserService userService = myCglib.MyCglibCreator();

System.out.println(userService.doFirst());
userService.doSecond();
}

}

最后更新: 2020年02月01日 17:08

原始链接: https://java4all.cn/2018/01/30/java动态代理和静态代理的实现/