天天看點

Java的代理對象執行個體

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

}