JAVA 静态代理和动态代理

JAVA 静态代理和动态代理

应用场合实例:权限管理

模拟需求:对业务bean里的所有方法进行拦截,拦截到方法之后判断用户是否有权限调用这个方法(判断依据:用户是否为null)

步骤一:先定义一个接口类

package proxy.service;

public interfacePersonService {

    public voidsave(String name);

    public voidupdate(String name, Integer personid);

}

 

 

步骤二:定义一个接口实现类

package proxy.service.impl;

import  proxy.service.PersonService;

public class PersonServiceBean implementsPersonService{

    privateString user = null;//提供一个用户

publicPersonServiceBean(){}

publicPersonServiceBean(String user){    this.user= user;  }

publicString getUser() {    return this.user;} //向外暴露一个获得用户的方法

    Public voidsave(String name) {   System.out.println("我是save()方法");}

    Public voidupdate(String name, Integer personid) {   System.out.println("我是update()方法");}

 }

 

实现方案1:

if(user != null)

缺点:如果要控制更多的业务bean里的业务方法,出现在各个业务方法里面去,代码写死不灵活,侵入性强。且权限判断依据一旦发生改变,所有业务方法里面的判断代码都需要修改。

改进1:过滤器(限于web应用)

改进2:采用代理设计模式(拦截并在拦截之后做相应的处理)【设计理念】

客户端应用-------------------------------》代理对象----------------------------------------》目标对象

 

 

 

 

 


客户端应用调用实际的目标对象之前先经过代理对象,也就是说客户端调用的是代理对象,代理对象实现了目标对象的所有接口,通过代理对象的调用,它会把方法的调用委派给目标对象,更形象的说,代理方法的内部调用了目标对象的方法,不需要在目标对象里编写判断代码,只需要在处理代理对象里面,目标对象调用之前做一个权限的判断,如果有权限才在代理对象里面调用目标对象的方法,如果没有权限就不调用目标对象的方法。

两种代理:静态代理和动态代理

 

 

实现方案2:

静态代理

package proxy.service.impl;

import proxy.service.PersonService;

public class  StaticProxy implements  PersonService {

    privatePersonService  personService;

    publicStaticProxy(PersonService  personService){   this.personService=personService;}

publicvoid save(String name) {

       PersonServiceBeanbean = (PersonServiceBean)this.personService;

       if(bean.getUser()!=null){bean.save(name);}

}

Public voidupdate(String name, Integer personid) {

       PersonServiceBeanbean = (PersonServiceBean)this.personService;

       if(bean.getUser()!=null){ bean.update(name, personid);}

}

}

缺点:对于接口中的每一个方法,所用的实现类和代理类都需要做个实现,增加了代码的复杂度。

实现方案3:

 动态代理

好处:接口中声明的所有方法都被转移到一个集中的方法中处理(invoke),不需要对接口中的每一个方法进行中转,动态代理类只能代理接口,且都需实现invocationhandler接口,覆盖invoke方法,该incoke方法就是调用被代理接口的所有方法时需要调用的。

JDK动态生成代理对象的字节码

Proxy为目标对象动态创建代理对象,应用前提:目标对象必须面向接口

思考的步骤属于“横切性关注点”

 

importjava.lang.reflect.InvocationHandler;

importjava.lang.reflect.Method;

importjava.lang.reflect.Proxy; 

importproxy.service.impl.PersonServiceBean;

publicclass JDKProxyFactory implementsInvocationHandler{

      private Object targetObject;

      public Object createProxyIntance(Object targetObject){

             this.targetObject= targetObject;

             return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),

                           this.targetObject.getClass().getInterfaces(),this);

//new一个代理实例,参数1为目标对象的类装载器,2为代理对象要实现的接口(创建目标对象的代理类,所以要实现目标对象里所有的接口,那么创建的代理对象会把这里面的接口全部实现),3为接口,回调,拦截到方法的时候会触发哪一个类的拦截方法,要求必修实现InvocationHandler接口

      PublicObject invoke(Object proxy, Method method, Object[] args)  {

//1为代理对象,2为被拦截到的方法,3为方法的输入参数

当客户端调用代理对象的方法时会调用this里面由InvocationHandler接口决定的invoke方法。委派给目标对象

PersonServiceBean  bean = (PersonServiceBean) this.targetObject;

             Object  result = null;

             if(bean.getUser()!=null){   result=method.invoke(targetObject, args);}

             return  result;

      } 

}

Test

packagejunit.test;

publicclass ProxyTest {

      @Test

public voidproxyTest(){

             JDKProxyFactoryfactory = new JDKProxyFactory();

             PersonService  service = (PersonService)factory.createProxyIntance(newPersonServiceBean("xxx"));

             service.save("888");

      }

      }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值