Java的代理对象,可以通过代理来操作一个正真的实例对象,通过代理模式来重写那些我们需要增强的原对象的方法,下面是一个关于代理的简单实例:
1.定义一个接口类
public interface MyBusiness {
public void method1();
public void method2();
}
2.实现上面接口的实现类
public class MyBusinessImpl implements MyBusiness {
@Override
public void method1() {
// TODO Auto-generated method stub
System.out.println("method1");
}
@Override
public void method2() {
// TODO Auto-generated method stub
System.out.println("method2");
}
}
3.通过一个代理对象重写原来对象的方法1
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyTestMain {
public static void main(String[] args) {
//创建真正的对象
final MyBusiness obj = new MyBusinessImpl();
//重写method1的实现---->不修改源码
//生成真正的代理对象
/*
Proxy.newProxyInstance(loader, 类加载器
obj, 真正对象实现的接口
arg2)InvocationHandler表示客户端如何调用代理对象
*/
MyBusiness proxyObj = (MyBusiness) Proxy.newProxyInstance(ProxyTestMain.class.getClassLoader(),
obj.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] params)
throws Throwable {
//客户端的一次调用
/*
* method: 客户端调用方法名
* params: 方法的参数
*/
if ("method1".equals(method.getName())) {
System.out.println("********重写了method1***********");
return null;
}else {
//不感兴趣的方法
return method.invoke(obj, params);
}
}
});
proxyObj.method1();
proxyObj.method2();
}
}
4.以上代码就是一个简单的通过Java代理实现的重写原来对象的方法
5.我们可以通过代理对象实现一个简单的数据库连接池
(1)实现数据库连接池类
import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;
import javax.sql.DataSource;
public class MyDataSourcePool implements DataSource {
//初始化连接池,放入10个连接
private static String driver = "com.mysql.jdbc.Driver";
private static String url = "jdbc:mysql://192.168.160.111:3306/hive";
private static String user = "hiveowner";
private static String password = "Welcome_1";
//定义一个链表来保存10个连接
private static LinkedList<Connection> dataSource = new LinkedList<>();
static{
try {
//注册驱动
Class.forName(driver);
for (int i = 0; i < 5; i++) {
dataSource.add(DriverManager.getConnection(url, user, password));
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Connection getConnection() throws SQLException {
// 从连接池中返回该连接
/*if (dataSource.size() > 0) {
return dataSource.removeFirst();
}else {
throw new SQLException("系统繁忙,请稍后");
}*/
//代理获取连接
//设置同步防止多线访问造成异常
synchronized (dataSource) {
if (dataSource.size() > 0) {
final Connection connection = dataSource.removeFirst();
Connection proxy = (Connection) Proxy.newProxyInstance(MyDataSourcePool.class.getClassLoader(),
connection.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 重写close方法
if ("close".equals(method.getName())) {
dataSource.add(connection);
return null;
} else {
return method.invoke(connection, args);
}
}
});
return proxy;
}else {
throw new SQLException("系统繁忙,请稍后");
}
}
}
@Override
public PrintWriter getLogWriter() throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
// TODO Auto-generated method stub
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
// TODO Auto-generated method stub
}
@Override
public int getLoginTimeout() throws SQLException {
// TODO Auto-generated method stub
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
// TODO Auto-generated method stub
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
// TODO Auto-generated method stub
return false;
}
@Override
public Connection getConnection(String username, String password)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
}
(2)测试连接池
import java.sql.Connection;
public class TestDataSourcePool {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
//从连接池中获取连接,使用完后释放连接
MyDataSourcePool pool = new MyDataSourcePool();
for (int i = 0; i < 11; i++) {
Connection conn = pool.getConnection();
System.out.println("第" + i + "个连接,是" + conn);
conn.close();
}
//多线程访问数据库连接池
Runnable runnable = new Runnable() {
@Override
public void run() {
MyDataSourcePool pool = new MyDataSourcePool();
for (int i = 0; i < 50; i++) {
Connection conn = null;
try {
conn = pool.getConnection();
System.out.println("第" + i + "个连接,是" + conn);
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
};
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
Thread t3 = new Thread(runnable);
Thread t4 = new Thread(runnable);
Thread t5 = new Thread(runnable);
Thread t6 = new Thread(runnable);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
}