动态代理

动态代理的使用

动态代理不用再手动创建代理类

/**
 * 类描述:
 *
 * @ClassName SmDataSource
 * @Description TODO
 * @Author 小鹏
 * @Date 2022/6/2 20:30
 * @Version 1.0
 */
public class SmDataSource {
    //链表集合
    private static LinkedList<Connection> list = new LinkedList<>();
    private String url;
    private String username;
    private String password;
    //连接池大小
    private Integer initSize;
    public SmDataSource(){

    }

    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //创建数据库连接对象,存入linkedlist中
    public void init(){
        for (int i = 0; i < initSize; i++) {
            try {
                Connection connection = DriverManager.getConnection(url, username, password);
                /*//创建代理对象  静态代理
                Connection connectionProxy = new ConnectionProxy(connection, this);*/
                /*
                    动态代理
                 */
                ClassLoader classLoader = SmDataSource.class.getClassLoader();
                Class[] interfaces = new Class[]{Connection.class};
                InvocationHandler handler = new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        String name = method.getName();
                        if ("close".equals(name)){
                            //如果是close方法,则执行我们写的back方法
                            //执行把connection代理对象放回连接池操作
                            //proxy就是要归还的connection代理对象,因为是connection代理对象调用了close方法

                            /**
                             * 因为connection对象调用了close方法,所以会回调该函数,并把connection自身传给proxy参数
                             *      所以调用close方法时,会进入SmDataSource对象内部
                             *
                             *  因为这个invocationhandler对象就在SmDataSource内部,invoke方法也在SMDataSource内部
                             *  所以,invoke内部可以直接调用SmDataSource的方法back()
                             */
                            back((Connection) proxy);
                        }
                        else{
                            //如果不是则执行被代理对象原来的方法
                            return method.invoke(connection,args);
                        }
                        return null;
                    }
                };

                Connection  connectionProxy =(Connection) Proxy.newProxyInstance(classLoader, interfaces,handler);


                list.add(connectionProxy);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public Connection getConn(){
        //弹出一个数据库连接池对象
        return list.pop();
    }
    /**
     * 需要执行的close方法
     */
    public void back(Connection connection) {
        //需要接收一个待关闭的connection对象
        list.addLast(connection);
    }

    //获取数据库连接池大小
    public int getSize(){
        return list.size();
    }

测试类

public class TextProxy {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //设置虚拟机参数,保存生成的代理对象
        System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles","true");

        SmDataSource smDataSource = new SmDataSource();
        smDataSource.setInitSize(10);
        smDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/704a");
        smDataSource.setUsername("root");
        smDataSource.setPassword("root");
        //执行数据库连接池初始化方法
        smDataSource.init();
        System.out.println("数据库连接池大小:"+smDataSource.getSize());
        //获取数据库连接对象
        Connection conn = smDataSource.getConn();
        PreparedStatement ps = conn.prepareStatement("select * from sys_user where id = ?");
        ps.setInt(1,1);
        ResultSet resultSet = ps.executeQuery();

        resultSet.next();
        String uname = resultSet.getString("uname");

        System.out.println(uname);
        conn.close();
        System.out.println("数据库连接池大小:"+smDataSource.getSize());

    }
}

posted @ 2022-06-03 14:40  重力体  阅读(60)  评论(0)    收藏  举报