代理---静态代理--动态代理

首先,明确一点:代理不会改变之前写的所有代码,代理需要继承相同的接口。

那么问题来了,为什么要用到代理?

假设有一个接口 UserManager, 这个接口中有很多待实现的方法,此时,有一个实现类实现了这个接口 UserManagetImpl, 并且已经上线,客户已经在使用了,所以讲道理来说,不管是接口或者实现类,都必须做到对修改关闭,对扩展开放。

此时,有一个问题,如果我们需要给接口中每一个方法的实现类的具体实现语句中,加入别的逻辑,比如增加安全性检查,或者增加事务和日志,则按照最简单的写法是,修改实现类 UserManagerImpl 的每一个方法,加上相应的语句即可。但是,这种做法违背了上面说的 对修改关闭 原则。

 

于是,出现了代理,这里的代理指的是静态代理。

// 接口  UserManager.java
 
public interface UserManager {

    public boolean addUser(String username, String password);

    public void delUser(int userId);

    public String findUserById(int userId);
  
    public void modifyUser(int userId, String username, String password);

}
// 接口的实现类 UserManagerImpl.java

public class UserManagerImpl implements UserManager {

  @Override
    public boolean addUser(String username, String password) {

       System.out.println("------UserManagerImpl.addUser-----");
       return true;
    }

  @Override
    public void delUser(int userId) {

       System.out.println("------UserManagerImpl.delUser-----");
    }

  @Override
    public String findUserById(int userId) {

       System.out.println("------UserManagerImpl.findUserById-----");
       return "zhangsan";
    }

  @Override
    public void modifyUser(int userId,String username, String password) {

       System.out.println("------UserManagerImpl.modifyUser-----");
    
    }

  @Override
    public void checkSecurity() {

       System.out.println("------UserManagerImpl.checkSecurity-----");
     
    }

}
//静态代理,需要实现同样的接口
//代理不会改变之前的代码,对修改关闭
//将实际的实现通过构造器传递到代理中,通过代理调用实际实现类中的具体实现方法

public class UserManagerProxy implements UserManager {

    private UserNamager userManager;
    public UserManagerProxy(UserNamager userManager) {

       this.userManager = userManager;
   }

  @Override
    public boolean addUser(String username, String password) {
       checkSecurity();
       userManager.addUser(username,password);
       return true;
    }

  @Override
    public void delUser(int userId) {
       checkSecurity();
       userManager.delUser(userId);
    }

  @Override
    public String findUserById(int userId) {
       checkSecurity();
       userManager.findUserById(userId);
       return "zhangsan";
    }

  @Override
    public void modifyUser(int userId,String username, String password) {
       checkSecurity();
       userManager.modifyUser();
    
    }

  @Override
    public void checkSecurity() {
       System.out.println("------UserManagerImpl.checkSecurity-----");
     
    }

}
//测试类 ProxyTest.java

public class ProxyTest {
 
     public static void main(String[] args) {
 
       //在测试类中传入具体实现类 UserManagerImpl,传到代理的构造器中
       UserManagerProxy  userManagerProxy  = new UserManagerProxy(new UserManagerImpl());
       System.out.println(userManagerProxy.addUser("zhangsan","123456"));
}


}

以上,是一个简单的静态代理的例子,最需要注意的点如下:

(1) 代理类和具体的实现类继承的是同一个接口

(2) 代理的实现对修改关闭,对扩展开放,也只是对具体实现类的扩展

(3) 客户端通过代理去间接的调用到具体的实现类,在代理中会增加一部分控制逻辑

静态代理缺陷: 在具体的实现类中有多少个接口,就需要加多少次逻辑,并且一次性只能代理一个固定的接口,不灵活,代码不简洁,所以出现了动态代理.

动态代理:

// 接口  UserManager.java
 
public interface UserManager {

    public boolean addUser(String username, String password);

    public void delUser(int userId);

    public String findUserById(int userId);
  
    public void modifyUser(int userId, String username, String password);

}
// 接口的实现类 UserManagerImpl.java

public class UserManagerImpl implements UserManager {

  @Override
    public boolean addUser(String username, String password) {

       System.out.println("------UserManagerImpl.addUser-----");
       return true;
    }

  @Override
    public void delUser(int userId) {

       System.out.println("------UserManagerImpl.delUser-----");
    }

  @Override
    public String findUserById(int userId) {

       System.out.println("------UserManagerImpl.findUserById-----");
       return "zhangsan";
    }

  @Override
    public void modifyUser(int userId,String username, String password) {

       System.out.println("------UserManagerImpl.modifyUser-----");
    
    }

}
//动态代理的核心类 SecurityHandler.java
//需要实现InvocationHandler 接口

public class SecurityHandler implements InvocationHandler {

    private Object targetObject;


    //通过 createProxyInstance 传入具体的实现类
    public Object createProxyInstance(Object targetObject) {

        this.targetObject = targetObject;
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
                                      targetObject.getClass().getInterfaces(), this);
 
    }
 
@Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
    //在 invoke 方法中加逻辑
      checkSecurity();

    //真正调用目标的方法
      Object o1 = method.invoke(targetObject,objects);
      return o1;

    }

    private void checkSecurity() {
     System.out.println("------checkSecurity-----");
    }

}
//动态代理测试类 

public class Client {

  SecurityHandler handler = new SecurityHandler();

  //动态生成
  //传入真正的实现类 UserManagerImpl
  UserManager userManager = (UserManager )handler.createProxyInstance(new UserManagerImpl());
  System.out.println(userManager.addUser("zhangsan","123456"));

}

代理必须依赖真正的实现类存在,代理不能直接做具体的业务实现,只是一个中间件的作用,在这个中间件中加了一些逻辑控制,如加入日志,加入权限控制等,具体的业务实现还需要具体的实现类来完成。所以代理不能单独存在,必须搭配实现类,并且和实现类实现同样的接口。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值