面试题答案
一键面试InvocationHandler
接口方法作用及工作机制
InvocationHandler
接口只有一个方法:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
- 方法作用:
- 当通过代理对象调用方法时,实际会调用到该
invoke
方法。 proxy
:指被代理的对象,在实际使用中可以用于某些情况下对代理对象自身的操作,但通常较少使用。method
:指被代理对象上被调用的方法对象,通过该对象可以获取方法的名称、参数类型等信息。args
:指调用方法时传入的参数数组,如果方法没有参数则为null
。
- 当通过代理对象调用方法时,实际会调用到该
- 工作机制:在动态代理创建代理对象时,会将
InvocationHandler
实例关联到代理对象上。当代理对象的方法被调用,JVM会将方法调用转发到InvocationHandler
的invoke
方法中。在invoke
方法内,可以根据method
和args
进行自定义的逻辑处理,比如方法调用前的预处理,方法调用后的后处理等,处理完成后返回相应的结果。
在事务管理场景中利用InvocationHandler
实现代理逻辑
假设我们有一个简单的服务层接口UserService
及其实现类UserServiceImpl
,现在要在UserService
方法调用前后添加事务管理逻辑。
- 定义服务层接口和实现类
public interface UserService {
void addUser(String username);
}
public class UserServiceImpl implements UserService {
@Override
public void addUser(String username) {
// 实际添加用户逻辑,这里简单打印
System.out.println("Adding user: " + username);
}
}
- 定义事务管理工具类
public class TransactionManager {
public void beginTransaction() {
System.out.println("Transaction started.");
}
public void commitTransaction() {
System.out.println("Transaction committed.");
}
public void rollbackTransaction() {
System.out.println("Transaction rolled back.");
}
}
- 实现
InvocationHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class TransactionInvocationHandler implements InvocationHandler {
private Object target;
private TransactionManager transactionManager;
public TransactionInvocationHandler(Object target, TransactionManager transactionManager) {
this.target = target;
this.transactionManager = transactionManager;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
transactionManager.beginTransaction();
try {
Object result = method.invoke(target, args);
transactionManager.commitTransaction();
return result;
} catch (Exception e) {
transactionManager.rollbackTransaction();
throw e;
}
}
}
- 创建代理对象
import java.lang.reflect.Proxy;
public class TransactionProxyFactory {
public static Object createTransactionProxy(Object target, TransactionManager transactionManager) {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new TransactionInvocationHandler(target, transactionManager)
);
}
}
- 测试事务管理代理
public class Main {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
TransactionManager transactionManager = new TransactionManager();
UserService proxy = (UserService) TransactionProxyFactory.createTransactionProxy(userService, transactionManager);
proxy.addUser("testUser");
}
}
在权限控制场景中利用InvocationHandler
实现代理逻辑
假设我们有一个DocumentService
接口及其实现类,现在要在调用DocumentService
方法前进行权限检查。
- 定义服务层接口和实现类
public interface DocumentService {
void readDocument(String documentId);
}
public class DocumentServiceImpl implements DocumentService {
@Override
public void readDocument(String documentId) {
System.out.println("Reading document with id: " + documentId);
}
}
- 定义权限检查工具类
public class PermissionChecker {
public boolean hasPermission(String userId, String action) {
// 这里简单返回true模拟有权限,实际需要根据业务逻辑检查
return true;
}
}
- 实现
InvocationHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class PermissionInvocationHandler implements InvocationHandler {
private Object target;
private PermissionChecker permissionChecker;
private String userId;
public PermissionInvocationHandler(Object target, PermissionChecker permissionChecker, String userId) {
this.target = target;
this.permissionChecker = permissionChecker;
this.userId = userId;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String action = method.getName();
if (permissionChecker.hasPermission(userId, action)) {
return method.invoke(target, args);
} else {
throw new RuntimeException("No permission to perform this action.");
}
}
}
- 创建代理对象
import java.lang.reflect.Proxy;
public class PermissionProxyFactory {
public static Object createPermissionProxy(Object target, PermissionChecker permissionChecker, String userId) {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new PermissionInvocationHandler(target, permissionChecker, userId)
);
}
}
- 测试权限控制代理
public class Main {
public static void main(String[] args) {
DocumentService documentService = new DocumentServiceImpl();
PermissionChecker permissionChecker = new PermissionChecker();
String userId = "123";
DocumentService proxy = (DocumentService) PermissionProxyFactory.createPermissionProxy(documentService, permissionChecker, userId);
proxy.readDocument("doc1");
}
}