Java设计模式之代理模式

Java设计模式之代理模式


Java中代理模式分为静态代理和动态代理,他们的作用是对类的功能的扩展,在不修改原有的类的基础上,增加新的功能,符合了开放闭包的原则(对修改关闭,对扩展开放)

1.静态代理


关键点: 代理要实现和代理对象同样的接口

logo

代码如下:

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
//接口
public interface Teacher{
void teach();
}
//代理对象
public MathTeacher implements Teacher{
public void teach(){
System.out.println("teach math.....");
}
}
//代理
public class TeacherProxy implements Teacher{
//赋予代理对象
private Teacher teacher;
public TeacherProxy(Teacher t){
this.teacher = t;
}
@override
public void teach(){
System.out.println("prepare.....");
//代理的对象中的方法
teacher.teach();
System.out.println("end....");
}
}
//程序入口部分
public static void main(String[] args){
Teacher t = new MathTeacher();
TeacherProxy proxy = new TeacherProxy(t);
proxy.teach();
}

输出结果:

prepare… teach math… end…

静态代理缺点: 当代理的对象实现多个接口,代理也要实现相应的接口,相应的代理也要增加接口中声明的方法,非常麻烦。

动态代理(jdk代理)

因为静态代理所带来的不便,从而引申出了动态代理,动态代理在运行期确定代理对象,存在内存中,通过jdk的Proxy类来实现。

代码如下:

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
public interface Teacher{
void teach();
}
//代理对象
public class MathTeacher{
public void teach(){
System.out.println("开始上课了...");
}
}
//代理工厂
public ProxyFactory{
//注入代理对象,编译期不确定,所以用Object
private Object target;
//通过构造方法,给代理对象赋值
public ProxyFactory(Object target){
this.target = target;
}
//通过代理对象为其创建一个代理
public Object getProxyInstance(){
//调用jdk proxy类的方法Proxy.newProxyInstance(代理对象的字节码加载器, 代理对象实现的接口, 事件触发器)
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//为代理类的方法附加其他的操作
System.out.println("before...");
Object result = method.invoke(target, args);
System.out.println("after...");
return result;
}
});
}
}

动态代理(Cglib代理)

和jdk代理不同的是,当需要代理的对象

AOP的基础。
1
2
3
代码实现:
这是一个需要被代理的类,也就是父类,通过字节码技术创建这个类的子类,实现动态代理。

public class SayHello {
public void say(){
System.out.println(“hello everyone”);
}
}

1
2
该类实现了创建子类的方法与代理的方法。getProxy(SuperClass.class)方法通过入参即父类的字节码,通过扩展父类的class来创建代理对象。intercept()方法拦截所有目标类方法的调用,obj表示目标类的实例,method为目标类方法的反射对象,args为方法的动态入参,proxy为代理类实例。proxy.invokeSuper(obj, args)通过代理类调用父类中的方法。

public class CglibProxy implements MethodInterceptor{
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
//设置需要创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
return enhancer.create();
}
//实现MethodInterceptor接口方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println(“前置代理”);
//通过代理类调用父类中的方法
Object result = proxy.invokeSuper(obj, args);
System.out.println(“后置代理”);
return result;
}
}

1
2
程序入口:

public class DoCGLib {
public static void main(String[] args) {
CglibProxy proxy = new CglibProxy();
//通过生成子类的方式创建代理类
SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class);
proxyImp.say();
}
}
```
输出结果:

前置代理
hello everyone
后置代理