18.动态代理-JDK

 

JDK动态代理

UserDao

1
2
3
4
5
6
7
8
package com.course.dao;

public interface UserDao1 {

public void addUser(String userName);

public void deleteUser(Integer userId);
}
1
2
3
4
5
6
package com.course.dao;

public interface UserDao2 {

public void queryUser(Integer userId);
}
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
package com.course.dao.impl;

import com.course.dao.UserDao1;
import com.course.dao.UserDao2;

public class UserDaoImpl implements UserDao1, UserDao2 {

@Override
public void addUser(String userName) {
System.out.println("Save user, userName = " + userName);

}

@Override
public void deleteUser(Integer userId) {
System.out.println("delete user, userId = " + userId);

}

@Override
public void queryUser(Integer userId) {
System.out.println("query user, user[userId=" + userId + ", userName=Jerry]");

}
}

DepartmentDao

1
2
3
4
5
6
package com.course.dao;

public interface DepartmentDao {

public void addDepartmentDao();
}
1
2
3
4
5
6
7
8
9
10
11
12
package com.course.dao.impl;

import com.course.dao.DepartmentDao;

public class DepartmentDaoImpl implements DepartmentDao {

@Override
public void addDepartmentDao() {
System.out.println("Save department");

}
}

ProxyFactory

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
package com.course.proxy;

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

public class ProxyFactory {

// 目标对象
private Object targetObject;

public ProxyFactory(Object targetObject) {
this.targetObject = targetObject;
}

/**
* 得到代理对象
* @return: 代理对象
*/
public Object getProxyInstance() {
/**
* Proxy.newProxyInstance()方法参数说明:
* - ClassLoader loader: 目标类的类加载器
* - Class<?>[] interfaces: 目标类实现的所有的接口的数组
* - InvocationHandler h: 当代理对象创建之后,调用目标对象的方法时触发的方法回调
*/
Object proxyObject = Proxy.newProxyInstance(
targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
new InvocationHandler() {

/**
* invoke()方法参数说明:
* - Object proxy: 代理对象
* - Method method: 所要调用的目标对象的方法
* - Object[] args: 目标对象的方法的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置加强
openTransaction();
// 执行目标对象的方法
Object invoke = method.invoke(targetObject, args);
// 后置加强
commitTransaction();
return invoke;
}
});
return proxyObject;
}

public void openTransaction() {
System.out.println("open transaction");
}

public void commitTransaction() {
System.out.println("commit transaction");
}

}

测试类

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
package com.course.test;

import com.course.dao.DepartmentDao;
import com.course.dao.UserDao1;
import com.course.dao.UserDao2;
import com.course.dao.impl.DepartmentDaoImpl;
import com.course.dao.impl.UserDaoImpl;
import com.course.proxy.ProxyFactory;

public class Test {

public static void main(String[] args) {
// 创建一个目标对象
UserDaoImpl userDaoImpl = new UserDaoImpl();
// 创建代理工厂对象
ProxyFactory userDaoProxyFactory = new ProxyFactory(userDaoImpl);
// 得到代理对象
UserDao1 userDaoProxy1 = (UserDao1) userDaoProxyFactory.getProxyInstance();
UserDao2 userDaoProxy2 = (UserDao2) userDaoProxyFactory.getProxyInstance();
// 执行目标方法
String userName = "Tom";
userDaoProxy1.addUser(userName);
/*
* open transaction
* Save user, userName = Tom
* commit transaction
*/
Integer userId = 1;
userDaoProxy1.deleteUser(userId);
/*
* open transaction
* delete user, userId = 1
* commit transaction
*/
userId = 2;
userDaoProxy2.queryUser(userId);
/*
* open transaction
* query user, user[userId=2, userName=Jerry]
* commit transaction
*/

// 创建一个目标对象
DepartmentDao departmentDao = new DepartmentDaoImpl();
// 创建代理工厂对象
ProxyFactory departmentDaoProxyFactory = new ProxyFactory(departmentDao);
// 得到代理对象
DepartmentDao departmentDaoProxy = (DepartmentDao) departmentDaoProxyFactory.getProxyInstance();
// 执行目标方法
departmentDaoProxy.addDepartmentDao();
/*
* open transaction
* Save department
* commit transaction
*/
}
}

总结

优点:有了目标对象,只要通过代理工厂就可以为所有的目标对象去创建代理对象,不用显式创建代理对象了。

缺点:目标对象必须至少实现一个接口,代理对象强制类型转换时只能转换为目标对象所实现的接口类型

原理:当调用Proxy.newProxyInstance方法时,系统会根据目标对象的类加载器和目标对象所实现的所有接口,在内存里创建一个实现了目标对象所有接口的代理类,并使用这个代理类创建了一个代理对象并返回。