代理模式

代理模式(Proxy)

属于结构型模式

Proxy-代理模式是指为其他对象提供一种代理,来控制对这个对象的访问

即对A对象进行代理后, 本来A对象的功能交给代理B来做; 代理就是原实例前后添加一层处理.

为什么使用代理模式

  • 授权机制: 不同级别的用户对于同一对象的访问权限是不同的, 要用代理实现对不同用户的访问权限的控制
  • 某个客户端不能直接操作一个对象, 但又要和那个对象互动, 也要通过代理实现间接互动
  • 代理类为委托类预处理消息,过滤消息,把消息传递给委托类, 以及事后对返回结果的处理等.

3种代理模式

1. 静态代理

实现步骤

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
// 第一步:创建服务类接口
public interface UserService{
void login();
}

// 第二步:实现服务接口
public class UserServiceImpl implements UserService{
@Override
public void login(){
System.out.println("登录");
}
}

// 第三步:创建代理类
public class UserServiceProxy implements UserService{
private UserService userService;

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

@Override
public void login(){
System.out.println("准备登录");
userService.login();
System.out.println("登录完成");
}
}

// 第四步:测试运行
public class ProxyTest{
public static void main(String[] args){
UserService userService=new UserServiceImpl();
UserServiceProxy userServiceProxy=new UserServiceProxy(userService);
userServiceProxy.login();
}
}

静态代理可以做到符合开闭原则的对目标对象进行功能扩展, 但是工作量大, 要给每个对象创建代理类, 而且不易管理, 接口发生改变, 代理类也要改变

2. JDK动态代理

动态代理中, 不需要手动创建代理类了, 只要编写一个动态处理器就OK了

实现步骤

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
// 第一步:编写动态代理
public class DynamicProxyHandler implements InvocationHandler{
private Object object;

public DynamicProxyHandler(final Object object){
this.object=object;
}

@Override
public Object invoke(Object proxy,Method method,Object[] agrs)throws Throwable{
System.out.println("准备");
Object result=method.invoke(Object,args);
System.out.println("完成");
return result;
}
}

// 第二步:编写测试类
public class DynamicProxyTest{
public static void main(String[] args){
UserService userService=new UserServiceImpl();
UserService userServiceProxy=(UserService)Proxy.newProxyInstnce(UserService.class.getClassLoader(),new Class[]{UserService.class},new DynamicProxyHandler(userService));
userServiceProxy.login();
}
}

3. CGLIB代理

JDK实现动态代理需要实现类通过接口定义业务的方法, 对于没有接口的类就不能实现代理.这就需要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
// 第一步:创建CGLIB代理类
public class CglibProxy implements MethodInterceptor{
private Object target;
public Object getInstance(final Object
target){
this.target=target;
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(This.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}

public Object intercept(Object object, Method method, Object[] args,MeyhodProxy methodProxy)throws Throwable{
System.out.println("准备");
Object result=method.invoke(object,args);
System.out.println("结束");
return result
}
}

// 第二步:创建测试类

public class CglibDynamicProxyTest{
public static void main(String[] args){
UserService userService=new UserServiceImpl();
CglibProxy cglibProxy=new CglibProxy();
UserService userServiceProxy=(UserService)cglibProxy.getInstance(userService1;)
userServiceProxy.login();
}
}

CGLIB代理比JDK代理的性能更高,但是CGLIB比JDK创建代理的耗时要更高,所以单例对象CGLIB更合适, 反之JDK更合适.

CGLIB动态代理执行流程