目录
  1. 1. 动态代理模式
    1. 1.1. 引言
    2. 1.2. 定义
    3. 1.3. 实现原理
    4. 1.4. 实现步骤
      1. 1.4.1. 第一步,创建实体类
      2. 1.4.2. 第二步,创建事务类
      3. 1.4.3. 第三步,创建共同接口
      4. 1.4.4. 第四步,创建被代理者的操作
      5. 1.4.5. 第五步,创建动态代理的抽象操作
      6. 1.4.6. 第六步,测试
    5. 1.5. 总结
    6. 1.6. 自然言语
动态代理模式

动态代理模式

引言

用的最广泛的设计模式

定义

在实现阶段不用关心代理的是那个,在运行阶段才指定具体的代理。

实现原理

动态代理技术中的代理能够做比静态代理技术中的代理更多,更广的事。动态代理能够根据被代理类提供的操作动态生成相对应的操作而替代被代理类实现。
可以这样比喻,动态代理就是一个集代购电子产品,服装,化妆品,食品等业务于一身的综合代购,被代理者(用户)不管你想进行那类操作,代购都能对应的帮你完成。
动态代理是jdk的技术,使用java.lang.reflect包下提供的Proxy类和InvacationHandler接口,可以生成一个动态代理类和代理对象。
InvacationHandler接口需要被实现而重写invoke(target,method,args)方法,将被代理者需要进行的操作(通过method.invoke()方法获取相对应操作)和代购需要进行的操作合并,形成代理需要进行的操作。 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
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
package com.test.bean;

/**
* 动态代理需要的被代理对象
*/
public class User {
private int id ;
private String name ;
private int age ;
private String sex ;

public User() {
}

public User(int id, String name, int age, String sex) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getSex() {
return sex;
}

public void setSex(String sex) {
this.sex = sex;
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
}

第二步,创建事务类
1
2
3
4
5
6
7
8
9
10
11
12
package com.test.transaction;

public class MyTransaction {
public void before(){
System.out.println("打开事务");
}

public void after(){
System.out.println("关闭事务");
}
}

第三步,创建共同接口
1
2
3
4
5
6
7
8
9
10
11
12
package com.test.service;

import com.test.bean.User;

/**
* 动态代理需要的公共接口
*/
public interface UserService {
public void addUser(User u);
public void delete(int id);
}

第四步,创建被代理者的操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.test.serviceImpl;

import com.test.bean.User;
import com.test.service.UserService;

/**
* 被代理对象需要做的动作
*/
public class UserServiceImpl implements UserService {
public void addUser(User u) {
System.out.println("增加用户");
}

public void delete(int id) {
System.out.println("删除用户");
}
}

第五步,创建动态代理的抽象操作
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
package com.test.serviceImpl;

import com.test.transaction.MyTransaction;

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

/**
* 动态代理的关键部分,通过实现InvocationHandler,用于表示在执行某个方法之前或者之后需要加入的代码
* 这里放置代理对象的执行过程
*/
public class ObjectIntercepter implements InvocationHandler {
private Object target ;
private MyTransaction myTransaction ;

public ObjectIntercepter() {
}

public ObjectIntercepter(Object target, MyTransaction myTransaction) {
this.target = target;
this.myTransaction = myTransaction;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
this.myTransaction.before();//开启事务
method.invoke(this.target , args); //获取需要代理的对象需要执行的操作
this.myTransaction.after();//提交事务
return null;
}
}

第六步,测试
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
import com.test.bean.User;
import com.test.service.UserService;
import com.test.serviceImpl.ObjectIntercepter;
import com.test.serviceImpl.UserServiceImpl;
import com.test.transaction.MyTransaction;
import org.junit.Test;

import java.lang.reflect.Proxy;

public class test {
UserService us = new UserServiceImpl();
MyTransaction mt = new MyTransaction();
ObjectIntercepter oi = new ObjectIntercepter(us,mt);


/**
* 这里使用Proxy类来创建一个代理实例,它通过获取被代理类的类加载器和接口,这样就能为新创建的代理类和被代理类有共同的接口
* 代理类创建之后,需要通过oi(动态勾连需要的操作)获取对应的操作
* oi传入目标对象(被代理类)和事务(需要的前置和后置条件),通过invoke函数将他们合并,形成代理类最终的操作
*
* 上述可获取代理类和匹配被代理类需要代理类完成的操作
*/

@Test
public void test(){
UserService userService = (UserService)Proxy.newProxyInstance(us.getClass().getClassLoader(), us.getClass().getInterfaces(), oi);
userService.delete(1);
}
}

总结

动态代理技术就相当于一个自动化工厂,将一个个不同型号的零部件适配组装成不同类型的产品。
理解动态代理,可以与静态代理相结合。动态代理的出现就是解决静态代理的缺陷。知道动态代理的功能后,顺藤摸瓜,就能知道动态代理的实现原理。

自然言语

忙了几天,终于抽出时间把动态代理这块给理清了。加上这个已经理清两个设计模式,有朝一日我要把java的23种设计模式都弄出来。
剩余:21种。

文章作者: rack-leen
文章链接: http://yoursite.com/2019/05/19/Java/Java%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E7%BB%93%E6%9E%84%E5%9E%8B%E6%A8%A1%E5%BC%8F/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 rack-leen's blog
打赏
  • 微信
  • 支付宝

评论