静态代理和动态代理

一、静态代理:代理类和目标类实现同一个接口,具备目标类的部分功能。

静态代理类优缺点 
优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。 
缺点: 
1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。 
2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。 

1.代理接口

public interface Base {
    //获得连接
    boolean getConnection();
    //查询数据
    ResultSet selectSQL(String sql, Object...obj);
    //增删改查
    int updateSQL(String sql,Object...obj);
    //关闭连接
    void closeConnection();

}

2.委托类

public class BaseDao implements Base{

    Connection connection=null;
    PreparedStatement pre=null;
    ResultSet resultSet=null;
    //关闭连接
    public void closeConnection(){
        if(resultSet!=null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(pre!=null){
            try {
                pre.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(connection!=null){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    //连接数据库
    public boolean getConnection(){
        String jdbc = ConfigManager.getInstance().getInfo("jdbc");
        String url = ConfigManager.getInstance().getInfo("url");
        String user = ConfigManager.getInstance().getInfo("user");
        String pwd = ConfigManager.getInstance().getInfo("pwd");
        try {
            //加载驱动
            Class.forName(jdbc);
            //获取连接
            connection = DriverManager.getConnection(url, user, pwd);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
    //查询语句
    public ResultSet selectSQL(String sql,Object...obj){
       // String sql="select * from student where stuname=?";
        try {
            pre = connection.prepareStatement(sql);
            for(int i=0;i<obj.length;i++){
                pre.setObject(i+1,obj[i]);
            }
            resultSet= pre.executeQuery();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return resultSet;
    }
    //增删改查
    public int updateSQL(String sql,Object...obj){
        int num=0;
        try {
            pre=connection.prepareStatement(sql);
            for(int i=0;i<obj.length;i++){
                pre.setObject(i+1, obj[i]);
            }
           num= pre.executeUpdate();

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return num;
    }
}

3.静态代理类

public class BaseAgent implements Base{
    Base base=new BaseDao();

    @Override
    public boolean getConnection() {

        return base.getConnection();
    }

    @Override
    public ResultSet selectSQL(String sql, Object... obj) {
        base.getConnection();
        ResultSet resultSet = base.selectSQL(sql, obj);
//        base.closeConnection();
        return resultSet;
    }

    @Override
    public int updateSQL(String sql, Object... obj) {
        base.getConnection();
        int num=base.updateSQL(sql,obj);
        base.closeConnection();
        return num;
    }

    @Override
    public void closeConnection() {
        base.closeConnection();
    }
}

4.测试类

public class TestCase {
    public static void main(String[] args) throws Exception{
        BaseAgent ba=new BaseAgent();
        String sql="select stuname from student where stuid=? or stuid=?;";
        ResultSet resultSet = ba.selectSQL(sql, 2,3);
        while(resultSet.next()){
            System.out.println(resultSet.getString("stuname"));
        }
        ba.closeConnection();
    }
}

二、动态代理 
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。

1.代理接口

public interface DoSame {
    void doSomething();
    void say();
}

2.目标类(实现代理接口)

public class DoSameImp implements DoSame {
    @Override
    public void doSomething() {
        System.out.println("必须做些什么!");
    }

    @Override
    public void say() {
        System.out.println("要说些什么?");
    }

3. 实现InvocationHandler接口创建自己的调用处理器

public class DoSameHandler implements InvocationHandler {
    private DoSame doSame;
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before========");
        //利用反射机制将请求分派给委托类处理。Method的invoke返回Object对象作为方法执行结果。
        Object invoke = method.invoke(doSame, args);
        System.out.println("after=========");
        return invoke;
    }
    //构造函数
    public DoSameHandler(){}
    public DoSameHandler(DoSame doSame){
        this.doSame=doSame;
    }
}

4.测试类

public class TestCase {
    public static void main(String[] args) throws Exception {
        DoSame doSame=new DoSameImp();
        // 通过 Proxy 直接创建动态代理类实例
        DoSame o =(DoSame) Proxy.newProxyInstance(doSame.getClass().getClassLoader(), new Class[]{DoSame.class},
                new DoSameHandler(doSame));
        System.out.println("目标对象调用如下:");
        doSame.doSomething();
        System.out.println("代理对象调用如下:");
        o.doSomething();
        //打印内存中的代理类
        byte[] bytes= ProxyGenerator.generateProxyClass("$Proxy0",new Class[]{DoSame.class});
        FileOutputStream fos=new FileOutputStream("$Proxy0.class");
        fos.write(bytes);
        fos.close();
    }
}
原文地址:https://www.cnblogs.com/TFE-HardView/p/11178001.html