查看: 62|回复: 2

[Mysql] MySQL第七天----Connection连接池、包装模式(装饰模式)与动态...

[复制链接]
  • TA的每日心情
    开心
    2017-8-13 08:16
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2019-7-12 22:40:35 | 显示全部楼层 |阅读模式

    在上次写的连接模板中,Connection是单例,只适用于单线程也就是一个用户操作,一旦多线程同时运行,就会挂掉,这里将探讨原因和解决办法。

    单例工厂类的漏洞

    这里写了一个类,专门对此做了测试:

    TxDemo.java

    [backcolor=white !important][size=1em][color=white !important]
    [color=white !important][size=1em]?

    [size=1em]1

    [size=1em]2

    [size=1em]3

    [size=1em]4

    [size=1em]5

    [size=1em]6

    [size=1em]7

    [size=1em]8

    [size=1em]9

    [size=1em]10

    [size=1em]11

    [size=1em]12

    [size=1em]13

    [size=1em]14

    [size=1em]15

    [size=1em]16

    [size=1em]17

    [size=1em]18

    [size=1em]19

    [size=1em]20

    [size=1em]21

    [size=1em]22

    [size=1em]23

    [size=1em]24

    [size=1em]25

    [size=1em]26

    [size=1em]27

    [size=1em]28

    [size=1em]29

    [size=1em]30

    [size=1em]31

    [size=1em]32

    [size=1em]33

    [size=1em]34

    [size=1em]35

    [size=1em]36

    [size=1em]37

    [size=1em]38

    [size=1em]39

    [size=1em]40

    [size=1em]41

    [size=1em]42

    [size=1em]43

    [size=1em]44

    [size=1em]45

    [size=1em]46

    [size=1em]47

    [size=1em]48

    [size=1em]49

    [size=1em]50

    [size=1em]51

    [size=1em]52

    [size=1em]53

    [size=1em]54

    [size=1em]55

    [size=1em]56

    [size=1em]57

    [size=1em]58

    [size=1em]59

    [size=1em]60

    [size=1em]61

    [size=1em]62

    [size=1em]63

    [size=1em]64

    [size=1em]65

    [size=1em]66

    [size=1em]67

    [size=1em]68

    [size=1em]69

    [size=1em]70

    [size=1em]71

    [size=1em]72

    [size=1em]73

    [size=1em]74

    [size=1em]75

    [size=1em]76

    [size=1em]77

    [size=1em]78

    [size=1em]79

    [size=1em]80

    [size=1em]81

    [size=1em]82

    [size=1em]83

    [size=1em]84

    [size=1em]85

    [size=1em]86

    [size=1em]87

    [size=1em]88

    [size=1em]89

    [size=1em]90

    [size=1em]91

    [size=1em]92

    [size=1em]93

    [size=1em]94

    [size=1em]95

    [size=1em]96

    [size=1em]97

    [size=1em]98

    [size=1em]99

    [size=1em]100

    [size=1em]101

    [size=1em][size=1em]<span style="font-size:14px;">package cn.hncu.tx;

    [size=1em]import java.sql.Connection;
    [size=1em]import java.sql.SQLException;
    [size=1em]import java.sql.Statement;

    [size=1em]import cn.hncu.pubs.ConnFactory;

    [size=1em]//使用的是单例连接工厂ConnFactory
    [size=1em]public class TxDemo {
    [size=1em]    /*
    [size=1em]     * 我这里开了四个线程,加上mian线程,共五个线程,每次拿Connection都是拿的同一个对象,
    [size=1em]     * 则这些线程之间会串数据,如:
    [size=1em]     * 我让main线程执行插入,然后在提交之前睡眠,让第三个线程执行插入时出错,
    [size=1em]     * 然后回滚,就会把main线程刚才所执行的全部回滚,main线程之前的动作全部无效,
    [size=1em]     * 若其他线程比三线程提前执行完,则把main线程的动作也一起提交了,若main线程下面出错,则无法回滚
    [size=1em]     * 这样不安全
    [size=1em]     */
    [size=1em]    public static void main(String[] args) {
    [size=1em]        Connection con = ConnFactory.getConn();
    [size=1em]        try {
    [size=1em]            Statement st = con.createStatement();
    [size=1em]            con.setAutoCommit(false);// 开启一个事务
    [size=1em]            st.executeUpdate("insert into person2 values('P07','赵子龙','1')");

    [size=1em]            MyThread th1 = new MyThread(1);
    [size=1em]            MyThread th2 = new MyThread(2);
    [size=1em]            MyThread th3 = new MyThread(3);
    [size=1em]            MyThread th4 = new MyThread(4);
    [size=1em]            th1.start();
    [size=1em]            th2.start();
    [size=1em]            th3.start();
    [size=1em]            th4.start();
    [size=1em]            Thread.sleep(1000);

    [size=1em]            con.commit();
    [size=1em]            System.out.println("main线程提交一个事务");
    [size=1em]        } catch (Exception e) {
    [size=1em]            try {
    [size=1em]                con.rollback();
    [size=1em]                System.out.println("main线程回滚一个事务");
    [size=1em]            } catch (SQLException e1) {
    [size=1em]                e1.printStackTrace();
    [size=1em]            }
    [size=1em]        } finally {
    [size=1em]            try {
    [size=1em]//              con.setAutoCommit(true);
    [size=1em]//              con.close();
    [size=1em]            } catch (Exception e) {
    [size=1em]                e.printStackTrace();
    [size=1em]            }

    [size=1em]        }
    [size=1em]    }
    [size=1em]}

    [size=1em]class MyThread extends Thread {
    [size=1em]    private int num;

    [size=1em]    public MyThread(int num) {
    [size=1em]        this.num = num;
    [size=1em]    }

    [size=1em]    @Override
    [size=1em]    public void run() {
    [size=1em]        Connection con = ConnFactory.getConn();
    [size=1em]        try {
    [size=1em]            Statement st = con.createStatement();
    [size=1em]            con.setAutoCommit(false);// 开启一个事务
    [size=1em]            String sql = "insert into person2 values('P07" + num + "','赵子龙"
    [size=1em]                    + num + "','1')";
    [size=1em]            if(num==3){
    [size=1em]                sql = "insert into person2 values('P07" + num + ",'赵子龙"
    [size=1em]                        + num + "','1')";
    [size=1em]            }else{
    [size=1em]                Thread.sleep(100);
    [size=1em]            }
    [size=1em]            //System.out.println("sql-----" + sql);
    [size=1em]            st.executeUpdate(sql);
    [size=1em]            con.commit();
    [size=1em]            System.out.println(num + "线程提交一个事务");

    [size=1em]        } catch (Exception e) {
    [size=1em]            try {
    [size=1em]                con.rollback();
    [size=1em]                System.out.println(num + "线程回滚一个事务");
    [size=1em]            } catch (SQLException e1) {
    [size=1em]                e1.printStackTrace();
    [size=1em]            } finally {
    [size=1em]                try {
    [size=1em]//                  con.setAutoCommit(true);
    [size=1em]//                  con.close();
    [size=1em]                } catch (Exception e1) {
    [size=1em]                    e1.printStackTrace();
    [size=1em]                }
    [size=1em]            }
    [size=1em]        }

    [size=1em]    }

    [size=1em]}</span>



    串数据:虽然main线程提交了事务,但是被3线程给回滚了,所以main线程做的插入动作也被回滚了,再提交也没用

    解决:要开一个连接池,池中放连接,对池做维护

    ConnUtils.java工具类

    [backcolor=white !important][size=1em][color=white !important]
    [color=white !important][size=1em]?

    [size=1em]1

    [size=1em]2

    [size=1em]3

    [size=1em]4

    [size=1em]5

    [size=1em]6

    [size=1em]7

    [size=1em]8

    [size=1em]9

    [size=1em]10

    [size=1em]11

    [size=1em]12

    [size=1em]13

    [size=1em]14

    [size=1em]15

    [size=1em]16

    [size=1em]17

    [size=1em]18

    [size=1em]19

    [size=1em]20

    [size=1em]21

    [size=1em]22

    [size=1em]23

    [size=1em]24

    [size=1em]25

    [size=1em][size=1em]<span style="font-size:14px;">package cn.hncu.pool;

    [size=1em]import java.sql.Connection;
    [size=1em]import java.sql.DriverManager;
    [size=1em]import java.util.ArrayList;
    [size=1em]import java.util.List;
    [size=1em]import java.util.Properties;

    [size=1em]//new出多个连接,放进池中,连接不再是单例,用池当单例
    [size=1em]public class ConnUtils {
    [size=1em]    private static List<connection> pool=new ArrayList<connection>();
    [size=1em]    private final static int NUM=3;
    [size=1em]    private ConnUtils(){
    [size=1em]    }
    [size=1em]    static{
    [size=1em]        Properties p=new Properties();
    [size=1em]        try {
    [size=1em]            p.load(ClassLoader.getSystemResourceAsStream("jdbc.properties"));//可从本类ConnUtils.Class.getClassLoader().getResourceAsStream("jdbc.properties")拿
    [size=1em]            String dirver=p.getProperty("driver");
    [size=1em]            String url=p.getProperty("url");
    [size=1em]            String user=p.getProperty("username");
    [size=1em]            String password=p.getProperty("password");
    [size=1em]            
    [size=1em]            Class.forName(dirver);
    [size=1em]            for(int i=0;i<num;i++){ catch="" con="DriverManager.getConnection(url," connection="" exception="" interruptedexception="" public="" return="" span="" static="" synchronized="" try="" void=""></num;i++){></connection></connection></span>




    TxDemo2.java测试类

    [backcolor=white !important][size=1em][color=white !important]
    [color=white !important][size=1em]?

    [size=1em]1

    [size=1em]2

    [size=1em]3

    [size=1em]4

    [size=1em]5

    [size=1em]6

    [size=1em]7

    [size=1em]8

    [size=1em]9

    [size=1em]10

    [size=1em]11

    [size=1em]12

    [size=1em]13

    [size=1em]14

    [size=1em]15

    [size=1em]16

    [size=1em]17

    [size=1em]18

    [size=1em]19

    [size=1em]20

    [size=1em]21

    [size=1em]22

    [size=1em]23

    [size=1em]24

    [size=1em]25

    [size=1em]26

    [size=1em]27

    [size=1em]28

    [size=1em]29

    [size=1em]30

    [size=1em]31

    [size=1em]32

    [size=1em]33

    [size=1em]34

    [size=1em]35

    [size=1em]36

    [size=1em]37

    [size=1em]38

    [size=1em]39

    [size=1em]40

    [size=1em]41

    [size=1em]42

    [size=1em]43

    [size=1em]44

    [size=1em]45

    [size=1em]46

    [size=1em]47

    [size=1em]48

    [size=1em]49

    [size=1em]50

    [size=1em]51

    [size=1em]52

    [size=1em]53

    [size=1em]54

    [size=1em]55

    [size=1em]56

    [size=1em]57

    [size=1em]58

    [size=1em]59

    [size=1em]60

    [size=1em]61

    [size=1em]62

    [size=1em]63

    [size=1em]64

    [size=1em]65

    [size=1em]66

    [size=1em]67

    [size=1em]68

    [size=1em]69

    [size=1em]70

    [size=1em]71

    [size=1em]72

    [size=1em]73

    [size=1em]74

    [size=1em]75

    [size=1em]76

    [size=1em]77

    [size=1em]78

    [size=1em]79

    [size=1em]80

    [size=1em]81

    [size=1em]82

    [size=1em]83

    [size=1em]84

    [size=1em]85

    [size=1em]86

    [size=1em]87

    [size=1em]88

    [size=1em]89

    [size=1em]90

    [size=1em]91

    [size=1em]92

    [size=1em]93

    [size=1em]94

    [size=1em]95

    [size=1em]96

    [size=1em]97

    [size=1em]98

    [size=1em][size=1em]<span style="font-size:14px;">package cn.hncu.tx;

    [size=1em]import java.sql.Connection;
    [size=1em]import java.sql.SQLException;
    [size=1em]import java.sql.Statement;

    [size=1em]import cn.hncu.pool.ConnUtils;
    [size=1em]import cn.hncu.pubs.ConnFactory;

    [size=1em]//使用的是多例连接工具ConnUtils
    [size=1em]public class TxDemo2 {
    [size=1em]     
    [size=1em]    public static void main(String[] args) {
    [size=1em]        Connection con = ConnUtils.getConn();
    [size=1em]        try {
    [size=1em]            Statement st = con.createStatement();
    [size=1em]            con.setAutoCommit(false);// 开启一个事务
    [size=1em]            st.executeUpdate("insert into person2 values('P07','赵子龙','1')");

    [size=1em]            MyThread2 th1 = new MyThread2(1);
    [size=1em]            MyThread2 th2 = new MyThread2(2);
    [size=1em]            MyThread2 th3 = new MyThread2(3);
    [size=1em]            MyThread2 th4 = new MyThread2(4);
    [size=1em]            th1.start();
    [size=1em]            th2.start();
    [size=1em]            th3.start();
    [size=1em]            th4.start();
    [size=1em]            Thread.sleep(1000);

    [size=1em]            con.commit();
    [size=1em]            System.out.println("main线程提交一个事务");
    [size=1em]        } catch (Exception e) {
    [size=1em]            try {
    [size=1em]                con.rollback();
    [size=1em]                System.out.println("main线程回滚一个事务");
    [size=1em]            } catch (SQLException e1) {
    [size=1em]                e1.printStackTrace();
    [size=1em]            }
    [size=1em]        } finally {
    [size=1em]            try {
    [size=1em]                con.setAutoCommit(true);
    [size=1em]//              con.close();
    [size=1em]                ConnUtils.back(con);//这里是回收Connection连接,应做成con.close(),池在背后回收资源,调用back方法
    [size=1em]            } catch (Exception e) {
    [size=1em]                e.printStackTrace();
    [size=1em]            }

    [size=1em]        }
    [size=1em]    }
    [size=1em]}

    [size=1em]class MyThread2 extends Thread {
    [size=1em]    private int num;

    [size=1em]    public MyThread2(int num) {
    [size=1em]        this.num = num;
    [size=1em]    }

    [size=1em]    @Override
    [size=1em]    public void run() {
    [size=1em]        Connection con = ConnUtils.getConn();
    [size=1em]        try {
    [size=1em]            Statement st = con.createStatement();
    [size=1em]            con.setAutoCommit(false);// 开启一个事务
    [size=1em]            String sql = "insert into person2 values('P07" + num + "','赵子龙"
    [size=1em]                    + num + "','1')";
    [size=1em]            if(num==2){
    [size=1em]                sql = "insert into person2 values('P07" + num + ",'赵子龙"
    [size=1em]                        + num + "','1')";
    [size=1em]            }else{
    [size=1em]                Thread.sleep(100);
    [size=1em]            }
    [size=1em]            //System.out.println("sql-----" + sql);
    [size=1em]            st.executeUpdate(sql);
    [size=1em]            con.commit();
    [size=1em]            System.out.println(num + "线程提交一个事务");

    [size=1em]        } catch (Exception e) {
    [size=1em]            try {
    [size=1em]                con.rollback();
    [size=1em]                System.out.println(num + "线程回滚一个事务");
    [size=1em]            } catch (SQLException e1) {
    [size=1em]                e1.printStackTrace();
    [size=1em]            } finally {
    [size=1em]                try {
    [size=1em]                    con.setAutoCommit(true);
    [size=1em]//                  con.close();
    [size=1em]                    ConnUtils.back(con);
    [size=1em]                } catch (Exception e1) {
    [size=1em]                    e1.printStackTrace();
    [size=1em]                }
    [size=1em]            }
    [size=1em]        }

    [size=1em]    }

    [size=1em]}
    [size=1em]</span>




    每个线程都独立开了,各不影响:


    装修模式:

    对Connection功能进行增强

    ConnUtils2.java

    由于本代码实现了Connection接口,代码较多,但大部分都是 不重要的,这里我只对改动的代码贴出来:

    在静态块for循环中

    [backcolor=white !important][size=1em][color=white !important]
    [color=white !important][size=1em]?

    [size=1em]1

    [size=1em]2

    [size=1em]3

    [size=1em]4

    [size=1em]5

    [size=1em]6

    [size=1em]7

    [size=1em]8

    [size=1em]9

    [size=1em]10

    [size=1em]11

    [size=1em]12

    [size=1em]13

    [size=1em]14

    [size=1em]15

    [size=1em]16

    [size=1em]17

    [size=1em]18

    [size=1em]19

    [size=1em]20

    [size=1em]21

    [size=1em]22

    [size=1em]23

    [size=1em]24

    [size=1em]25

    [size=1em]26

    [size=1em]27

    [size=1em]28

    [size=1em]29

    [size=1em]30

    [size=1em]31

    [size=1em]32

    [size=1em]33

    [size=1em]34

    [size=1em]35

    [size=1em]36

    [size=1em]37

    [size=1em]38

    [size=1em]39

    [size=1em]40

    [size=1em]41

    [size=1em]42

    [size=1em]43

    [size=1em]44

    [size=1em]45

    [size=1em]46

    [size=1em]47

    [size=1em]48

    [size=1em]49

    [size=1em]50

    [size=1em]51

    [size=1em]52

    [size=1em]53

    [size=1em]54

    [size=1em]55

    [size=1em]56

    [size=1em]57

    [size=1em]58

    [size=1em]59

    [size=1em]60

    [size=1em]61

    [size=1em]62

    [size=1em]63

    [size=1em]64

    [size=1em]65

    [size=1em]66

    [size=1em]67

    [size=1em]68

    [size=1em]69

    [size=1em]70

    [size=1em]71

    [size=1em]72

    [size=1em]73

    [size=1em]74

    [size=1em]75

    [size=1em]76

    [size=1em]77

    [size=1em]78

    [size=1em]79

    [size=1em]80

    [size=1em]81

    [size=1em]82

    [size=1em]83

    [size=1em]84

    [size=1em]85

    [size=1em]86

    [size=1em]87

    [size=1em]88

    [size=1em]89

    [size=1em]90

    [size=1em]91

    [size=1em]92

    [size=1em]93

    [size=1em]94

    [size=1em]95

    [size=1em]96

    [size=1em]97

    [size=1em]98

    [size=1em]99

    [size=1em]100

    [size=1em]101

    [size=1em]102

    [size=1em]103

    [size=1em]104

    [size=1em]105

    [size=1em]106

    [size=1em]107

    [size=1em]108

    [size=1em]109

    [size=1em]110

    [size=1em]111

    [size=1em]112

    [size=1em]113

    [size=1em]114

    [size=1em]115

    [size=1em]116

    [size=1em]117

    [size=1em]118

    [size=1em]119

    [size=1em]120

    [size=1em]121

    [size=1em]122

    [size=1em]123

    [size=1em]124

    [size=1em]125

    [size=1em]126

    [size=1em]127

    [size=1em]128

    [size=1em]129

    [size=1em]130

    [size=1em]131

    [size=1em]132

    [size=1em]133

    [size=1em]134

    [size=1em]135

    [size=1em]136

    [size=1em]137

    [size=1em]138

    [size=1em]139

    [size=1em]140

    [size=1em]141

    [size=1em]142

    [size=1em]143

    [size=1em]144

    [size=1em]145

    [size=1em]146

    [size=1em]147

    [size=1em]148

    [size=1em]149

    [size=1em]150

    [size=1em]151

    [size=1em]152

    [size=1em]153

    [size=1em]154

    [size=1em]155

    [size=1em]156

    [size=1em]157

    [size=1em]158

    [size=1em]159

    [size=1em]160

    [size=1em]161

    [size=1em]162

    [size=1em]163

    [size=1em]164

    [size=1em]165

    [size=1em]166

    [size=1em]167

    [size=1em]168

    [size=1em]169

    [size=1em]170

    [size=1em]171

    [size=1em]172

    [size=1em]173

    [size=1em]174

    [size=1em]175

    [size=1em]176

    [size=1em]177

    [size=1em]178

    [size=1em]179

    [size=1em]180

    [size=1em]181

    [size=1em]182

    [size=1em]183

    [size=1em]184

    [size=1em]185

    [size=1em]186

    [size=1em]187

    [size=1em]188

    [size=1em]189

    [size=1em]190

    [size=1em]191

    [size=1em]192

    [size=1em]193

    [size=1em]194

    [size=1em]195

    [size=1em]196

    [size=1em]197

    [size=1em]198

    [size=1em]199

    [size=1em]200

    [size=1em]201

    [size=1em]202

    [size=1em]203

    [size=1em]204

    [size=1em]205

    [size=1em]206

    [size=1em]207

    [size=1em]208

    [size=1em]209

    [size=1em]210

    [size=1em]211

    [size=1em]212

    [size=1em]213

    [size=1em]214

    [size=1em]215

    [size=1em]216

    [size=1em]217

    [size=1em]218

    [size=1em]219

    [size=1em]220

    [size=1em]221

    [size=1em]222

    [size=1em]223

    [size=1em]224

    [size=1em]225

    [size=1em]226

    [size=1em]227

    [size=1em]228

    [size=1em]229

    [size=1em]230

    [size=1em]231

    [size=1em]232

    [size=1em]233

    [size=1em]234

    [size=1em]235

    [size=1em]236

    [size=1em]237

    [size=1em]238

    [size=1em]239

    [size=1em]240

    [size=1em]241

    [size=1em]242

    [size=1em]243

    [size=1em]244

    [size=1em]245

    [size=1em]246

    [size=1em][size=1em]for(int i=0;i<num;i++){ con="new" conn="DriverManager.getConnection(url," connection="" myconnection="" pre=""><p>这里用到了MyConnection内部类</p><pre class="brush:sql;"><span style="font-size:14px;">//采用包装模式(装修模式)对Connection con功能进行增强
    [size=1em]    //因为是静态块中new  MyConnection 同时还要访问静态变量pool,所以要声明成静态,不然new 的时候会出现错误
    [size=1em]     static class MyConnection implements Connection {
    [size=1em]        private Connection con;
    [size=1em]        public MyConnection(Connection con){
    [size=1em]            this.con=con;
    [size=1em]        }
    [size=1em]</span>     </pre>
    [size=1em]<p>下面都是实现Connection抽象方法,我们只对close方法进行更改,其余还是用原来的</p>
    [size=1em]<pre class="brush:sql;"><span style="font-size:14px;">//功能增强就是这个地方,把close方法,改成放回池中
    [size=1em]        @Override
    [size=1em]        public void close() throws SQLException {
    [size=1em]            System.out.println("往池中还回一个连接------"+this);
    [size=1em]            pool.add(this);//注意这里要放this
    [size=1em]        }</span></pre>
    [size=1em]<p><br>
    [size=1em]TxDemo3.java中也只是把原先的ConnUtils.back(con)方法,改成con.close()方法,其余与TxDemo2.java相同,这里不再重叙。</p>
    [size=1em]<p> </p>
    [size=1em]<p>结果也是正确的:</p>
    [size=1em]<p><img alt="\" src="/uploadfile/Collfiles/20161111/2016111109200433.png" style="width: 630px; height: 190.189px;"></p>
    [size=1em]<p> </p>
    [size=1em]<h1>代理模式:</h1>
    [size=1em]<p>代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。</p>
    [size=1em]<p><img alt="\" src="/uploadfile/Collfiles/20161111/2016111109200434.png" style="width: 630px; height: 382.974px;"></p>
    [size=1em]<p> </p>
    [size=1em]<p>代理模式的初期引入:</p>
    [size=1em]<p>房东与租客:</p>
    [size=1em]<p>Renter.java</p>
    [size=1em]<pre class="brush:sql;">package cn.hncu.proxy.rent;

    [size=1em]public class Renter implements IRenter {
    [size=1em]    @Override
    [size=1em]    public void rent(){
    [size=1em]        System.out.println("房东:租出房子,收取房租");
    [size=1em]    }

    [size=1em]    @Override
    [size=1em]    public String toString() {
    [size=1em]        return "好好保护我的房子....";
    [size=1em]    }
    [size=1em]     
    [size=1em]     
    [size=1em]}
    [size=1em]</pre>
    [size=1em]<p>IRenter.java</p>
    [size=1em]<pre class="brush:sql;">package cn.hncu.proxy.rent;

    [size=1em]public interface IRenter {
    [size=1em]    public abstract void rent();
    [size=1em]}</pre>
    [size=1em]<p><br>
    [size=1em]Client.java</p>
    [size=1em]<pre class="brush:sql;">package cn.hncu.proxy.rent;

    [size=1em]import java.lang.reflect.InvocationHandler;
    [size=1em]import java.lang.reflect.Method;
    [size=1em]import java.lang.reflect.Proxy;

    [size=1em]public class Client {

    [size=1em]    public static void main(String[] args) {
    [size=1em]        final Renter r=new Renter();//被代理对象-----原型对象
    [size=1em]         
    [size=1em]        Object newObj=Proxy.newProxyInstance(
    [size=1em]                //ClassLoader loader, Class<!--?-->[] interfaces, InvocationHandler h
    [size=1em]                Client.class.getClassLoader(),
    [size=1em]                new Class[]{IRenter.class},
    [size=1em]                new InvocationHandler() {
    [size=1em]                     
    [size=1em]                    @Override//参数:proxy是代理后的对象(和外面的newObj一样的),method是当前被调用的method对象,args是当前method对象的参数
    [size=1em]                    public Object invoke(Object proxy, Method method, Object[] args)
    [size=1em]                            throws Throwable {
    [size=1em]                        if(method.getName().equals("rent")){
    [size=1em]                            System.out.println("给中介交点费用...");
    [size=1em]                            return method.invoke(r, args);
    [size=1em]                        }
    [size=1em]                        
    [size=1em]                        return method.invoke(r, args);//这里是放行,不做任何拦截,只是从这里过了一下
    [size=1em]                    }
    [size=1em]                });
    [size=1em]         
    [size=1em]        /*
    [size=1em]         * 代理后的对象newObj和原型对象r 是不同类型的对象。二者属于兄弟关系,都是IRenter接口的实现类(子类)
    [size=1em]         * 因此newObj是无法强转成Renter类型
    [size=1em]         */
    [size=1em]         
    [size=1em]        //代理后的newObj通常都是强转换成接口类型来使用
    [size=1em]        IRenter ir=(IRenter)newObj;
    [size=1em]        ir.rent();
    [size=1em]         
    [size=1em]        String str=ir.toString();
    [size=1em]        System.out.println(str);
    [size=1em]    }

    [size=1em]}
    [size=1em]</pre>
    [size=1em]<p> </p>
    [size=1em]<p>运行结果图:</p>
    [size=1em]<p><br>
    [size=1em]<img alt="\" src="/uploadfile/Collfiles/20161111/2016111109200435.png" style="width: 319px; height: 128px;"></p>
    [size=1em]<p> </p>
    [size=1em]<p><strong>连接池用代理模式:</strong></p>
    [size=1em]<p>ConnnUtils3.java</p>
    [size=1em]<pre class="brush:sql;">package cn.hncu.pool;

    [size=1em]import java.lang.reflect.InvocationHandler;
    [size=1em]import java.lang.reflect.Method;
    [size=1em]import java.lang.reflect.Proxy;
    [size=1em]import java.sql.Connection;
    [size=1em]import java.sql.DriverManager;
    [size=1em]import java.util.ArrayList;
    [size=1em]import java.util.List;
    [size=1em]import java.util.Properties;

    [size=1em]//new出多个连接,放进池中,连接不再是单例,用池当单例
    [size=1em]public class ConnUtils3 {
    [size=1em]    private static List<connection> pool=new ArrayList<connection>();
    [size=1em]    private final static int NUM=3;
    [size=1em]    private ConnUtils3(){
    [size=1em]    }
    [size=1em]    static{
    [size=1em]        Properties p=new Properties();
    [size=1em]        try {
    [size=1em]            p.load(ClassLoader.getSystemResourceAsStream("jdbc.properties"));//可从本类ConnUtils.Class.getClassLoader().getResourceAsStream("jdbc.properties")拿
    [size=1em]            String dirver=p.getProperty("driver");
    [size=1em]            String url=p.getProperty("url");
    [size=1em]            String user=p.getProperty("username");
    [size=1em]            String password=p.getProperty("password");
    [size=1em]            
    [size=1em]            Class.forName(dirver);
    [size=1em]            for(int i=0;i<num;i++){ catch="" conn="DriverManager.getConnection(url," connection="" exception="" final="" interruptedexception="" method="" new="" newobj="Proxy.newProxyInstance(" object="" override="" pre="" public="" return="" static="" synchronized="" throwable="" throws="" try=""><p>

    [size=1em]测试类与测试结果和上次的一样,这里不再贴出。</p><p>通用模板:</p><p>ProxyUtils.java</p><pre class="brush:sql;">package cn.hncu.proxy.util;

    [size=1em]import java.lang.reflect.InvocationHandler;
    [size=1em]import java.lang.reflect.Method;
    [size=1em]import java.lang.reflect.Proxy;

    [size=1em]public class ProxyUtils implements InvocationHandler {
    [size=1em]    private Object obj;
    [size=1em]    private ProxyUtils(Object obj){
    [size=1em]        this.obj=obj;
    [size=1em]    }
    [size=1em]    public static Object getProxy(Object obj){
    [size=1em]        Object newObj=Proxy.newProxyInstance(
    [size=1em]                ProxyUtils.class.getClassLoader(),
    [size=1em]                obj.getClass().getInterfaces(),
    [size=1em]                new ProxyUtils(obj));//构造传参
    [size=1em]        return newObj;
    [size=1em]    }
    [size=1em]    @Override
    [size=1em]    public Object invoke(Object proxy, Method method, Object[] args)
    [size=1em]            throws Throwable {
    [size=1em]         
    [size=1em]        System.out.println("前面拦拦:......");
    [size=1em]        Object resObj=method.invoke(obj, args);
    [size=1em]        System.out.println("后面拦拦:......");
    [size=1em]         
    [size=1em]         
    [size=1em]        return resObj;
    [size=1em]    }
    [size=1em]}
    [size=1em]</pre>
    [size=1em]<p> </p>
    [size=1em]<p>测试模板:</p>
    [size=1em]<p>人和狗</p>
    [size=1em]<p>dog.java</p>
    [size=1em]<pre class="brush:sql;">package cn.hncu.proxy.util;

    [size=1em]public class Dog implements IDog {
    [size=1em]    private String name;
    [size=1em]    public Dog(){
    [size=1em]        this.name="小黑";
    [size=1em]    }
    [size=1em]    /* (non-Javadoc)
    [size=1em]     * @see cn.hncu.proxy.util.IDog#bark()
    [size=1em]     */
    [size=1em]    @Override
    [size=1em]    public void bark(){
    [size=1em]        System.out.println(name+": 汪``汪``汪``");
    [size=1em]    }
    [size=1em]}
    [size=1em]</pre>
    [size=1em]<p><br>
    [size=1em]IDog.java</p>
    [size=1em]<pre class="brush:sql;">package cn.hncu.proxy.util;

    [size=1em]public interface IDog {

    [size=1em]    public abstract void bark();

    [size=1em]}</pre>
    [size=1em]<p>Person.java</p>
    [size=1em]<pre class="brush:sql;">package cn.hncu.proxy.util;

    [size=1em]public class Person implements IPerson {
    [size=1em]    private String name;
    [size=1em]    public Person(String name){
    [size=1em]        this.name=name;
    [size=1em]    }
    [size=1em]     
    [size=1em]    /* (non-Javadoc)
    [size=1em]     * @see cn.hncu.proxy.util.IPerson#sayHi()
    [size=1em]     */
    [size=1em]    @Override
    [size=1em]    public void sayHi(){
    [size=1em]        System.out.println("Hello,I am "+name);
    [size=1em]    }
    [size=1em]     
    [size=1em]}
    [size=1em]</pre>
    [size=1em]<p><br>
    [size=1em]IPerson.java</p>
    [size=1em]<pre class="brush:sql;">package cn.hncu.proxy.util;

    [size=1em]public interface IPerson {

    [size=1em]    public abstract void sayHi();

    [size=1em]}</pre>
    [size=1em]<p><br>
    [size=1em]Client.java</p>
    [size=1em]<pre class="brush:sql;">package cn.hncu.proxy.util;

    [size=1em]public class Client {

    [size=1em]    public static void main(String[] args) {
    [size=1em]        Dog dog=new Dog();
    [size=1em]        IDog dog2=(IDog) ProxyUtils.getProxy(dog);
    [size=1em]         
    [size=1em]        Person p=new Person("二牛");
    [size=1em]        IPerson p2=(IPerson) ProxyUtils.getProxy(p);
    [size=1em]         
    [size=1em]        p2.sayHi();
    [size=1em]        System.out.println("------------------------");
    [size=1em]        dog2.bark();
    [size=1em]    }

    [size=1em]}
    [size=1em]</pre>
    [size=1em]<p><br>
    [size=1em]运行结果:</p>
    [size=1em]<p><img alt="\" src="/uploadfile/Collfiles/20161111/2016111109200536.png" style="width: 371px; height: 190px;"><br>
    [size=1em] </p>
    [size=1em]</num;i++){></connection></connection></pre>
    [size=1em]</num;i++){>



    您需要登录后才可以回帖 登录 | 注册青鸟豆号

    本版积分规则

    Copyright 1999-2019 Beijing Aptech Beida Jade Bird Information Technology Co.,Ltd

    北大青鸟IT教育 北京阿博泰克北大青鸟信息技术有限公司 版权所有

    京ICP备11045574号-3 京公网安备11010802013845号

    快速回复 返回顶部 返回列表