在代码中调用close时也可以还连接
仔细讲解
转自:http://blog.csdn.net/xinxinqiu/article/details/17531449
对close方法进行修改。
类加载器
系统加载字节码是从下层往上层找的 如果父类没有就继续找父类 找到根加载器之后再往下加载 系统不允许操作根加载器 所以返回值永远是null、
动态代理
作用:
1:对某个方法增强。
2:在不污染源类的情况下,修改原类的行为。
代理类,与被代理类,两个不同的实体。
要求:
所有被代理的类,都必须要拥有一个接口。
本质上是对方法进行修改,但其实它是通过反射执行的某个方法。
1:对某个方法增强。
2:在不污染源类的情况下,修改原类的行为。
代理类,与被代理类,两个不同的实体。
要求:
所有被代理的类,都必须要拥有一个接口。
本质上是对方法进行修改,但其实它是通过反射执行的某个方法。
动态代理的核心类
Proxy – 用于创建给定接口的子类,在内存中动态的创建。$Proxy0. - 此类只使用一次。 InovocationHandler – 执行句柄。在执行时可以获取被代理类的所有反射。 - 用户的每一次调用都会被这个句柄拦截到。
代理举例
被代理类实现的接口
- public interface IGDG {
- String talk();
- }
被代理类
- public class GDG implements IGDG {
- int nu = 0;
- public GDG(int nm) {
- nu=nm;
- }
- public String talk(){
- System.err.println("5.1:开始讲了....."+nu);
- return "你好:"+nu;
- }
- }
代理实现
- public class ProxyDemo {
- public static void main(String[] args) throws Exception {
- final Object o = new GDG(3);//匿名内部类只能访问final成员
- System.err.println("o1 is:"+o+","+o.getClass());//GDG@4a5ab2,class cn.itcast.demo.GDG
- //使用Proxy类创建IGDG接口的子类
- Object proxyedObj =
- Proxy.newProxyInstance(ProxyDemo.class.getClassLoader(), //用哪一个类加载器在内存中加载一个IGDG的子类
- new Class[]{IGDG.class},//创建哪些接口的子类
- new InvocationHandler(){
- public Object invoke(Object proxy,
- Method method, Object[] args)
- throws Throwable {
- System.err.println("你正在执行的方法名为:"+method.getName());
- Object returnValue = method.invoke(o,args);
- return returnValue;
- }
- });
- //将proxyedObj强转成IGDG
- IGDG o2 = (IGDG) proxyedObj;
- o2.talk();
- System.err.println("-------");
- System.err.println("o2 is:"+o2+","+o2.getClass());
- }
仔细讲解
- public class ProxyDemo2 {
- public static void main(String[] args) throws Exception {
- final GDG o = new GDG(4);
- System.err.println("1:声明被代理的对象"+o+","+o.getClass());
- Object proxyedObj =
- Proxy.newProxyInstance(
- ProxyDemo2.class.getClassLoader(),
- new Class[]{IGDG.class},//必须填接口
- new InvocationHandler() {
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- System.err.println("5:正在调用的方法是:"+method.getName());//talk
- Object returnValue = method.invoke(o,args);
- System.err.println("6:通过反射调用目标(被代理类)类的方法成功,返回值是:"+returnValue);
- return "你不好";
- }
- }
- );
- System.err.println("2:代理类创建完成:"+proxyedObj.getClass());
- System.err.println("3:强转成IGDG接口");
- IGDG o2 = (IGDG) proxyedObj;
- System.err.println("4:调用代理类的talk方法");
- String back = o2.talk();
- System.err.println("7:方法都调用完成\t"+back);
- }
- }
- 输出结果
- 1:声明被代理的对象cn.itcast.demo.GDG@1c68b6f,class cn.itcast.demo.GDG
- 2:代理类创建完成:class com.sun.proxy.$Proxy0
- 3:强转成IGDG接口
- 4:调用代理类的talk方法
- 5:正在调用的方法是:talk
- 5.1:开始讲了.....4
- 6:通过反射调用目标(被代理类)类的方法成功,返回值是:你好:4
- 7:方法都调用完成 你不好
代理list
- public class ListProxy {
- public static void main(String[] args) throws Exception {
- final List list = new ArrayList();
- //声明代理
- Object oo = Proxy.newProxyInstance(
- ListProxy.class.getClassLoader(),
- new Class[]{List.class}
- ,
- new InvocationHandler() {
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- //执行被代理类的方法
- System.err.println("正在执行的方法是:"+method.getName());
- if(args!=null){
- for(Object arg:args){
- System.err.println("参数:"+arg);
- }
- }
- Object returnVal = method.invoke(list,args);
- if(method.getName().equals("size")){//调用的是否是size方法
- System.err.println("其实是:"+returnVal);
- return 1000;
- }
- return returnVal;
- }
- });
- List list2 = (List) oo;
- // list2.add("Jack");
- //
- // int size = list2.size();
- // System.err.println("大小是:"+size);
- //
- System.err.println("-----------");
- list.add("Rose");//1
- list.add("Jack");
- System.err.println("=====================");
- int size = list2.size();
- System.err.println("大小是:"+size);//1
- }
- }
用动态代理书写连接池
设计:
代理的目标:原生的connection。
代理的目的:修改close方法,让close方法不可以关闭连接,且主动收回连接。
通过动态代理,和线程通讯:
1:对Cxonnection进行代理。
2:在获取Connection时,通过同步,如果没有连接时,就让线程进入等待池。
3:修改close方法,且在还了连接以后唤醒正在等待的线程。
代理的目标:原生的connection。
代理的目的:修改close方法,让close方法不可以关闭连接,且主动收回连接。
通过动态代理,和线程通讯:
1:对Cxonnection进行代理。
2:在获取Connection时,通过同步,如果没有连接时,就让线程进入等待池。
3:修改close方法,且在还了连接以后唤醒正在等待的线程。
- public class ConnUtils4 {
- //第一步:声明连接池维护所有的连接
- private static List<Connection> pool = new ArrayList<Connection>();
- //第二步:静态代码块中创建多个连接
- static{
- try{
- Class.forName("com.mysql.jdbc.Driver");
- String url = "jdbc:mysql:///db909?characterEncoding=UTF8";
- for(int i=0;i<3;i++){
- final Connection con = DriverManager.getConnection(url,"root","1234");//com.mysql.jdbc.Jdbc4Connection@
- //对con对象进行动态代理
- Object proxyedCon =
- Proxy.newProxyInstance(
- ConnUtils4.class.getClassLoader(),
- new Class[]{Connection.class},
- //声明执行句柄,只对close方法设置拦截
- new InvocationHandler() {
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- if(method.getName().equals("close")){
- System.err.println("有人想关闭连接,不能关,还连接");
- //将proxy再加到pool中,这个proxy就是proxyedCon
- synchronized (pool) {
- pool.add((Connection) proxy);
- pool.notify();
- }
- return null;
- }else{
- System.err.println("放行"+method.getName());
- return method.invoke(con, args);
- }
- }
- });
- //一定要将代理对象添加到池中去。
- pool.add((Connection) proxyedCon);
- }
- }catch(Exception e){
- throw new RuntimeException(e.getMessage(),e);
- }
- }
- /**
- * 提供一个静态工厂方法返回一个连接
- */
- public static Connection getCon(){
- synchronized (pool) {
- if(pool.size()==0){
- try {
- pool.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- return getCon();
- }
- Connection con = pool.remove(0);//返回一个代理的connection对象
- System.err.println("还有几个:"+pool.size());
- return con;
- }
- }
- }