SSM框架中用到的设计模式-动态代理and责任链模式

SSM框架中用到的设计模式-动态代理and责任链模式


动态代理模式和责任链模式

代理对象

​ 通过一张图说明:

在这里插入图片描述

​ 在软件公司中,客户不会直接找到公司的软件工程师,而是通过商务,和商务谈判,此时的软件工程师是不需要处理谈判的内容,此处的商务就是代理的对象,他代理了软件工程师谈判。
​ 在真实对象(软件工程师)访问之前或之后加入对应逻辑,或其他规则控制是否使用真实对象。
​ 三者的关系:客户(调用者) , 商务(代理对象),软件工程师(真实对象)


常用的动态代理

​ 一般最常用的动态代理分为两种:一种是JDK动态代理,是JDK自带的功能。另一种是CGLIB,这是第三方提供的技术。


JDK动态代理

​ JDK动态代理通过包java.lang.reflect.*提供方式。必须借助一个借口才能产生代理对象。所以:

public interface HelloWorld{
    public void sayHelloWorld();
}

​ 实现接口

public class HelloWorldImpl implements HelloWorld{
   @Override
    public void sayHelloWorld(){
        System.out.println("Hello World");
    }
}

​ 要实现代理逻辑类必须去实现java.lang.reflect.InvocationHandler接口,它里面定义了一个invoke方法,并且提供接口数组用于下挂代理对象

//创建一个代理类,通过实现InvocationHandler接口完成
public class JdkProxyExample implements InvocationHandler{
    //真实对象(如一开始的图,软件工程师)
    private Object target=null;
    
    //建立代理对象和真实对象的代理关系,并且返回代理对象
    public Object bind(Object target){
        this.target=target;
        //通过代理类Proxy的方法newInstance创建代理对象并且返回代理对象
        return Proxy.newInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
    
    //代理方法逻辑
    @Override
    //proxy代理对象,method当前调度方法,args当前方法参数,retrun代理返回结果
    public Object invoke(Object proxy,Method method,Object[] args){
        System.out.println("进入代理逻辑方法");
        System.out.println("在调度真实对象之前的服务");
        //相当于调用了sayHelloWord()方法
        Object obj=method.invoke(target,args);
        System.out.println("在调度真实对象之后的服务");
        return obj;
    }
}

分析:

  1. 使用bind方法建立代理对象和现实对象的关系,方法里通过类的属性target保存的真实对象,然后通过代理类的newProxyInstance方法代理对象

    其中newProxyInstance方法中的三个参数分别代表:

    • 第一个是类加载器,这里采用了target本身的类加载器
    • 第二个是把生成代理对象下挂在哪些接口下,这个写法就是放在target实现的接口下
    • 第三个是定义实现方法逻辑的代理类,this表示当前对象,它必须实现InvocationHandler接口的invoke方法,他就是代理逻辑方法的实现方法
  2. 实现代理逻辑方法。invoke方法可以实现代理逻辑,该方法中有三个参数:

    • proxy:代理对象,bind方法生产的对象
    • method:当前调度方法
    • args:调度方法的参数

CGLIB动态代理

​ 这种第三方动态代理优势在于不需要提供接口,只需要一个非抽象类就能实现动态代理。

public class CglibProxyExample implements MethodInterceptor{
    //生产CGLIB代理对象
    public Object getProxy(Class cls){
        //CGLIB enhancer增强类对象
        Enhancer enhancer=new Enhancer();
        //设置增强类形
        enhancer.setSuperclass(cls);
        //定义代理逻辑对象为当前对象,要求当前对象实现MethodInterceptor方法
        enhancer.setCallback(this);
        //生成并返回代理对象
        return enhancer.create();
    }
    
    
    //代理逻辑方法
    @Override 
    public Object intercept(Object proxy,Method method,Object[] args,MethodProxy methodProxy)
    throws Throwable{
        System.out.println("调用真实对象前");
        //CGLIB反射调用真实对象方法
        Object result=methodProxy.invokeSuper(proxy,args);
        System.out.println("调用真实对象后");
        return result;
    }
}

​ 通过使用CGLIB的增强者Enhancer,通过设置父类方法setSuperclass,在通过setCallback设置哪个类为代理类。intercept方法则是其代理类的逻辑方法。


拦截器

​ 通过JDK动态代理实现拦截器功能,首先要定义接口Interceptor


public interface Interceptor {
    //方法的参数为 proxy 理对象,target 真实对象、 method 方法、 args 运行方法参数。
	public boolean before (Object proxy , Object target , Method method , Object []args) ;
	public void around(Object proxy, Object target , Method method , Object[]args) ;
	public void after(Object proxy, Object target, Method method , Object [ ]args);
}
  • before方法返回boolean值,当返回true时候,则返回反射真实对象的方法,否则调用around方法
  • before方法为false情况下,调用around方法
  • 在反射真实对象或执行了around方法之后,调用after方法

实现Interceptor接口

public class Myinterceptor implements Interceptor {
	Override
	public boolean before (Object proxy , Object target , Method method , Object []args) {
		System.err.println (”反射方法前逻辑) ;
		return false ;//不反射被代理对象原有方法
    }
                           
	@Override
	public roid after(Object proxy, Object target , Method method , Ob] ect []]args) {
		System.err.println ("反射方法后逻辑";
    }
            
	@Override
	public void around(Object proxy, Object target , Method method , Object[]args) {
		System err.println ("取代了被代理对象的方法");
        }
    }

​ JDK动态代理中使用拦截器:

public class InterecptorJdkProxy implements InvoctionHandeler{
    //真实对象
    private Object target;
    //拦截器全限定名
    private String interceptorClass=null;
    
    public InterecptorJdkProxy(Object target, String interceptorClass){
        this.target=target;
        this.interceptorClass=interceptorClass;
    }
    
    
    //绑定委托对象并返回一个代理占位
    public static Object bind(Object target, String interceptorClass){
        //取得代理对象
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),
                                     new InterecptorJdkProxy(target,interceptorClass));
        
    }
    
    //通过代理对象调用方法,首先进入这个方法
    @Override
    public Object invoke(Object proxy, Method method, Object []args)throws hrowable{
        
        if(interceptorClass==null){
            //没有设置拦截器则直接返回反射原有的方法
           	return method.invoke(target,args);
        }
        
        Object result=null;
        //通过反射生成拦截器
        Interceptor interceptor=(Interceptor)Class.forName(interceptorClass).newInstance();
        
        //调用前置方法
        if(interceptor.before(proxy,target,method,args)){
            //反射原有对象方法
            result=method.invoke(target,args);
        }else{
            interceptor.around(proxy,target,method,args);
        }
        
        //调用后置方法
        interceptor.after(proxy,target,method,args);
        return result;
    }
}

​ 执行流程:

  1. 在bind方法中用JDK动态代理绑定一个对象,并返回代理对象
  2. 如果没有拦截器,则直接返回真实对象的方法,然后结束,否则进入第三步
  3. 通过反射生成拦截器,并准备使用它
  4. 调用拦截器before方法,返回为true,反射原来的方法; 否则运行拦截器around方法
  5. 调用拦截器after方法
  6. 返回结构

责任链模式

​ 当一个对象在一条链上被多个拦截器拦截处理时,就把这种模式成为责任链模式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值