代理模式jdk动态代理,cglib字节码代理

设计模式-代理模式

常见设计模式分三大类:

  1. 创建模式:
    工厂方法, 抽象工厂, 建造模式, 原型模式, 单例模式5种.
  2. 结构模式:
    适配器模式, 桥梁模式, 代理模式, 装饰模式, 门面模式5种.
  3. 行为模式:
    模板模式, 迭代器模式, 观察者模式, 状态模式, 策略模式5种.

代理模式

代理可以实现给原有的方法增加逻辑,隐藏具体实现的复杂细节等.JDK从1.3版本开始就引入了动态代理并且经常用来动态的创建代理,但是JDK的代理依赖接口这点对于某些应用场景下带来了局限性.还好还有一种叫做cglib的包通过字节码增强(依赖字节码处理框架ASM)的方式现实了代理.
性能:在生成代理的操作jdk默认的动态代理性能是cglib的好多倍左右,可能这也是为什么spring默认使用jdk代理的原因.但是执行速度cglib时jdk代理快的多.所以大家在使用spring管理bean的使用可以根据scope的设置来配合代理包的使用,spring的scope为prototype时为了延迟实例化bean建议使用jdk默认代理;为singleton时单例默认启动的时候就实例化对象了所以建议使用cglib代理.

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
48
49
50
51
52
53
package com.xh.model.proxy;

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

/**
* Created by xiehui1956(@)gmail.com on 17-1-4.
*/
public class ProxyModel {

/**
* 声明接口
*/
interface StudentService {
void printStudentName();

void printStudentAge();
}

/**
* 接口实现
*/
static class StudentServiceImpl implements StudentService {

@Override
public void printStudentName() {
System.out.println(" Student name is san ");
}

@Override
public void printStudentAge() {
System.out.println(" Student age is 18");
}
}

public static void main(String[] args) throws Exception {
StudentService instance =
(StudentService) Proxy.newProxyInstance(StudentService.class.getClassLoader(), new Class[]{StudentService.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long start = System.nanoTime();
Object invoke = method.invoke(new StudentServiceImpl(), args);
System.out.println("方法执行时间: " + (System.nanoTime() - start));
return invoke;
}
});
instance.printStudentName();
instance.printStudentAge();

}
}

jdk动态代理依赖接口Spring的Bean容器默认使用的就是jdk动态代理,所以Controller层常换成cglib方式代理还有spring的aop面向切面没有接口依赖所以也是使用cglib代理.多说句在使用spring的时候需要注意他的很多特性都是给予代理实现的,如果在使用的时候不是使用spring管理的bean或者绕过了spring这层那么他的特性设置是无效的.常见的场景有事务管理,依赖注入等.

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
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
package com.xh.model;

import net.sf.cglib.proxy.*;

import java.lang.reflect.Method;

/**
* Created by xiehui1956(@)gmail.com on 17-1-4.
*/
public class StudentController {

public void printStudentName() {
System.out.println(" Student name is san");
}

public void printStudentAge() {
System.out.println(" Student age is 18");
}

/**
* 代理方法过滤器
* 可以在这里设置需要代理的情况,可以很灵活的使用这个方法.
* 例如从数据库取不需要代理的方法或者通过注解配置设置需要代理的方法等.
*/
public static class StudentFilter implements CallbackFilter {

/**
* 代理逻辑
*
* @param method
* @return 0:执行过滤; 1:不执行过滤
*/
public int accept(Method method) {

//此处可以使用正则
if ("printStudentName".equals(method.getName())) {
return 0;
}
return 1;
}
}

public static class StudentProxy implements MethodInterceptor {

private Enhancer enhancer = new Enhancer();

/**
* NoOp.INSTANCE是cglib所提供的,实质时一个没有任何操作的拦截器
*
* @param klass
* @return
*/
public Object getProxy(Class klass) {
enhancer.setSuperclass(klass);
// enhancer.setCallback(this); 单个
enhancer.setCallbacks(new Callback[]{this, NoOp.INSTANCE});
enhancer.setCallbackFilter(new StudentFilter());
return enhancer.create();
}

/**
* 增强逻辑
*
* @param obj
* @param method
* @param args
* @param proxy
* @return
* @throws Throwable
*/
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("调用的方法是: " + method.getName());
System.out.println("before" + method.getName());
Object invokeSuper = proxy.invokeSuper(obj, args);
System.out.println("after");
return invokeSuper;
}

}

public static void main(String[] args) {
StudentProxy studentProxy = new StudentProxy();
StudentController studentController =
(StudentController) studentProxy.getProxy(StudentController.class);
studentController.printStudentAge();
studentController.printStudentName();
}

}

以上.