代理模式(Proxy)
代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的访问。代理模式又分静态代理和动态代理,动态代理又分jdk动态代理和CGLB动态代理
静态代理模式
定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类,然后可通过客户端进行调用。
例如: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//接口
public interface PrintService {
void Print();
}
//被代理类
public class PrintServiceImpl implements PrintService {
public void Print() {
System.out.println("打印方法");
}
}
//代理类
public class StaticProxy implements PrintService{
private PrintService printService;
public StaticProxy(PrintService printService) {
this.printService = printService;
}
public void Print() {
//代理类调用原对象的方法
printService.Print();
this.check();
}
public void check(){
System.out.println("代理的额外操作");
}
//为了方便就不另写一个类定义客户端了
public static void main(String[] args) {
//创建目标对象
PrintService printService=new PrintServiceImpl();
//代理对象,把目标对象传给代理对象,建立代理关系
PrintService printService= new StaticProxy(printService);
printService.Print();
}
}
结果:
打印方法
代理的额外操作
动态模式—-JDK动态代理
静态代理只能实现
一个代理类服务一种接口
,对于多个代理类这时候需要使用动态代。在程序运行时,通过反射机制动态地创建一个代理类。但是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//接口
public interface PrintService {
void Print();
}
//被代理类
public class PrintServiceImpl implements PrintService {
public void Print() {
System.out.println("打印方法");
}
}
//实现InvocationHandler接口
public class JDKProxy implements InvocationHandler{
private Object target;
public JDKProxy(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//利用反射调用代理的方法
Object result=method.invoke(target,args);
return result;
}
}
public class TestJDKProxy {
public static void main(String[] args) throws Throwable {
//目标对象
PrintService printServiceImpl=new PrintServiceImpl();
//把目标对象传给代理对象,建立代理关系
InvocationHandler handler=new JDKProxy(printServiceImpl);
//创建代理类的实例
PrintService printService= (PrintService) Proxy.newProxyInstance(printServiceImpl.getClass().getClassLoader(),printServiceImpl.getClass().getInterfaces(),handler);
printService.Print();
}
}
结果:
打印方法
动态模式—-CGLB动态代理
CGLB动态代理和JDK动态代理和静态代理最大的不同就是前者可以以目标对象子类的方式类实现代理(即可以代理没有实现接口的类),后两者代理对象必须是实现了接口。CGLB动态代理它需要导入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
public class Print {
public void Display(){
System.out.println("打印方法。。。");
}
}
public class CGLBProxy implements MethodInterceptor{
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object result=methodProxy.invokeSuper(o,objects);
return null;
}
}
public class TestCGLBProxy {
public static void main(String[] args) throws Exception {
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(Print.class);
enhancer.setCallback(new CGLBProxy());
Print print= (Print) enhancer.create();
print.Display();
}
}