下面是Java 代理(Proxy)的原理及应用的详细攻略:
什么是Java代理?
Java代理是一种为其他对象提供代理服务的模式。代理是一种中介,它在客户端和实际对象之间起到缓冲的作用,使得客户端可以通过代理来访问对象。
Java代理的核心思想是:通过代理来访问实际对象,代理可以实现对实际对象的一些控制和管理,如访问控制、数据验证、安全控制等。
Java代理的分类
Java代理主要有两种形式:静态代理和动态代理。
静态代理
静态代理是由程序员编写代理类或特定工具自动生成源代码来实现代理。实现静态代理需要定义接口或父类,代理对象与目标对象实现相同的接口或继承相同的父类。
示例:定义一个接口Subject,其中包括一个抽象方法request(),然后实现一个RealSubject类和一个代理类ProxySubject,代理类可以在执行前和执行后做些额外的操作,如记录日志、验证用户等。
/**
* 接口Subject
*/
public interface Subject {
void request();
}
/**
* 实现类RealSubject
*/
public class RealSubject implements Subject {
public void request() {
System.out.println("RealSubject:真实请求");
}
}
/**
* 代理类ProxySubject
*/
public class ProxySubject implements Subject {
private RealSubject realSubject;
public ProxySubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
public void request() {
System.out.println("ProxySubject:代理前操作");
realSubject.request();
System.out.println("ProxySubject:代理后操作");
}
}
动态代理
动态代理是在程序运行时创建一个实现某些接口的代理类的实例。动态代理通常是使用反射机制实现。动态代理可以在实际对象方法执行前后添加额外的操作,如统计执行时间、记录日志等。
示例:使用Java提供的动态代理机制来实现代理类,实际对象必须实现接口。
/**
* 实现类RealSubject
*/
public class RealSubject implements Subject {
public void request() {
System.out.println("RealSubject:真实请求");
}
}
/**
* InvocationHandler接口实现类DynamicProxy
*/
public class DynamicProxy implements InvocationHandler {
private Object target;
public DynamicProxy(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("DynamicProxy:代理前操作");
Object result = method.invoke(target, args);
System.out.println("DynamicProxy:代理后操作");
return result;
}
}
/**
* 客户端调用
*/
public class Client {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
InvocationHandler handler = new DynamicProxy(realSubject);
Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler);
subject.request();
}
}
Java代理的应用
Java代理可以应用于许多场景,这里仅举两个例子:
数据库连接池
数据库连接池是一种连接管理工具,可以减少建立和断开数据库连接的频率,提高应用程序的性能。代理模式可以完成一个抽象工厂的功能,将代理作为工厂,用代理创建对象并进行统一的管理和维护。
示例:定义一个接口DbConnection,然后实现一个代理类DbConnectionProxy,在创建实际对象时,利用代理进行统一管理,如数据库连接的初始化、关闭等操作。
/**
* 数据库连接接口
*/
public interface DbConnection {
Connection getConnection();
void close(Connection connection);
}
/**
* 代理类DbConnectionProxy
*/
public class DbConnectionProxy implements DbConnection {
private List<Connection> connections = new ArrayList<>();
private static final int MAX_CONNECTIONS = 5;
public DbConnectionProxy() {
for (int i = 0; i < MAX_CONNECTIONS; i++) {
connections.add(createConnection());
}
}
public Connection getConnection() {
Connection connection = null;
if (connections.size() > 0) {
connection = connections.remove(0);
System.out.println("DbConnectionProxy:从连接池获取一条连接");
}
return connection;
}
public void close(Connection connection) {
if(connections.size() < MAX_CONNECTIONS) {
connections.add(connection);
System.out.println("DbConnectionProxy:归还一条连接到连接池中");
} else {
try {
connection.close();
System.out.println("DbConnectionProxy:关闭一条连接");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
private Connection createConnection() {
Connection connection = null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
System.out.println("DbConnectionProxy:创建一条新的连接");
} catch (SQLException | ClassNotFoundException e) {
e.printStackTrace();
}
return connection;
}
}
/**
* 客户端调用
*/
public class Client {
public static void main(String[] args) {
DbConnection dbConnection = new DbConnectionProxy();
Connection connection1 = dbConnection.getConnection();
Connection connection2 = dbConnection.getConnection();
Connection connection3 = dbConnection.getConnection();
Connection connection4 = dbConnection.getConnection();
dbConnection.close(connection4);
dbConnection.close(connection3);
dbConnection.close(connection2);
dbConnection.close(connection1);
}
}
rpc调用
RPC框架是一种远程调用框架,可以实现进程间的数据交换和互相调用,实现分布式系统之间的通信。代理模式可以实现rpc框架中的远程服务调用,使得客户端可以使用代理来访问服务端的方法。
示例:定义一个接口UserService,然后实现一个代理类UserProxy,利用代理来进行服务方法的远程调用。
/**
* 用户服务接口
*/
public interface UserService {
String getNameById(int id);
}
/**
* 代理类UserProxy
*/
public class UserProxy implements UserService {
private String host;
private int port;
public UserProxy(String host, int port) {
this.host = host;
this.port = port;
}
public String getNameById(int id) {
String result = null;
try (Socket socket = new Socket(this.host, this.port);
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
//请求消息
oos.writeUTF("UserService");
oos.writeUTF("getNameById");
oos.writeInt(id);
oos.flush();
//接收回应消息
result = ois.readUTF();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
/**
* 服务端实现UserService接口
*/
public class UserServiceImpl implements UserService {
public String getNameById(int id) {
//模拟实现 getNameById 接口
return "Alice";
}
}
/**
* 服务端调用
*/
public class Server {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(8888)) {
System.out.println("server starting...");
while (true) {
Socket socket = serverSocket.accept();
System.out.println("client connected");
//接收请求消息
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
String serviceName = ois.readUTF();
String methodName = ois.readUTF();
int id = ois.readInt();
//反射调用服务方法
Object serviceObject = getService(serviceName);
Method method = serviceObject.getClass().getMethod(methodName, int.class);
String result = (String) method.invoke(serviceObject, id);
//发送回应消息
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeUTF(result);
oos.flush();
socket.close();
System.out.println("client disconnected");
}
} catch (IOException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
private static Object getService(String serviceName) {
if("UserService".equals(serviceName)) {
return new UserServiceImpl();
}
return null;
}
}
/**
* 客户端调用
*/
public class Client {
public static void main(String[] args) {
UserService userService = new UserProxy("127.0.0.1", 8888);
String result = userService.getNameById(123);
System.out.println(result);
}
}
以上就是Java代理(Proxy)的原理及应用的完整攻略,希望对您有帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java 代理(Proxy)的原理及应用 - Python技术站