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();
}
}