zoukankan      html  css  js  c++  java
  • 【sping揭秘】12、SpringAOP的实现机制

    SpringAOP的实现机制

    设计模式代理模式

    参考我之前的代理模式

    http://www.cnblogs.com/cutter-point/p/5226642.html

    这里写个简单的案例

    package spring.aop.designPattern;
    
    /**
     * 
     * Title: ISubject.java
     * Description:代理模式的资源接口类 
     * @author xiaof
     * @date 2018年4月7日
     * @version 1.0 
     *
     */
    public interface ISubject {
        
        public void request();
    }
    package spring.aop.designPattern;
    
    /**
     * 
     * Title: SubjectImpl.java
     * Description: 被访问者,或者被访问的资源实现类
     * @author xiaof
     * @date 2018年4月7日
     * @version 1.0 
     *
     */
    public class SubjectImpl implements ISubject {
    
        @Override
        public void request() {
            // TODO Auto-generated method stub
            System.out.println("this is subjectImpl cutter_point ! ");
        }
    
    }
    package spring.aop.designPattern;
    
    /**
     * 
     * Title: SubjectProxy.java
     * Description: 代理实现类
     * @author xiaof
     * @date 2018年4月7日
     * @version 1.0 
     *
     */
    public class SubjectProxy implements ISubject {
    
        
        private ISubject subject;
        
        @Override
        public void request() {
            System.out.println("pre operation subjectproxy");
            if(subject != null) 
                subject.request();
            
            System.out.println("after operation subjectproxy");
        }
    
        public ISubject getSubject() {
            return subject;
        }
    
        public void setSubject(ISubject subject) {
            this.subject = subject;
        }
    
        
    }
    package spring.aop.designPattern;
    
    import org.junit.Test;
    
    public class Main {
    
        @Test
        public void test1() {
            SubjectImpl si = new SubjectImpl();
            SubjectProxy sp = new SubjectProxy();
            sp.setSubject(si);
            
            sp.request();
        }
    }

    测试一波:

     

    这就是,比如我们要对subjectimpl进行代理的时候,我们就需要根据ISubject接口实现一个代理类对象

    好,基于此点,

    缺点1:如果我们一个类不存在接口类型,并且是第三方的类对象,比如我们现在有一个subjectimpl2,这个类没有实现ISubject接口,那么我们的subjectimpl还能进行代理吗?显然是不能的

    缺点2:我们发现对一个subjectimpl对象进行代理就要实现一个代理类subjectProxy,那如果我们项目用有一个万类对象需要进行代理,那么我们需要创建一万个proxy类,好吧,我反正会疯的。。。

    动态代理

    这个jdk的动态代理主要是,proxy类和invocationhandler接口

    package spring.aop.designPattern;
    
    /**
     * 
     * Title: ISubject.java
     * Description:代理模式的资源接口类 
     * @author xiaof
     * @date 2018年4月7日
     * @version 1.0 
     *
     */
    public interface ISubject {
        
        public void request();
    }
    package spring.aop.designPattern;
    
    /**
     * 
     * Title: SubjectImpl.java
     * Description: 被访问者,或者被访问的资源实现类
     * @author xiaof
     * @date 2018年4月7日
     * @version 1.0 
     *
     */
    public class SubjectImpl implements ISubject {
    
        @Override
        public void request() {
            // TODO Auto-generated method stub
            System.out.println("this is subjectImpl cutter_point ! ");
        }
    
    }

    代理类

    package spring.aop.dynamicPorxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.util.Date;
    
    import spring.aop.util.DateUtil;
    
    /**
     * 
     * Title: RequestCtrlInvocationHandler.java
     * Description: jdk动态代理对象
     * @author xiaof
     * @date 2018年4月7日
     * @version 1.0 
     *
     */
    public class RequestCtrlInvocationHandler implements InvocationHandler {
        
        /**
         * 代理对象
         */
        private Object target;
        /**
         * 00:00:00
         */
        private String beginTime;
        /**
         * 00:00:00
         */
        private String endTime;
        
    
        public RequestCtrlInvocationHandler(Object target, String beginTime, String endTime) {
            this.target = target;
            this.beginTime = beginTime;
            this.endTime = endTime;
        }
    
    
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //判断是否是request方法,如果是进行拦截操作
            if(method.getName().equals("request")) {
                //判断当前时间是否在区间内,如果是,那么就进行相应的操作
                if(DateUtil.isInDate(new Date(), beginTime, endTime)) {
                    System.out.println("区间内时间,拦截成功");
                    return method.invoke(target, args);
                } else {
                    System.err.println("区间外时间");
                    return null;
                }
            }
            return method.invoke(target, args);
        }
    
    }

    最后测试:

    目前时间!

     

    那么我们修改时间区间,看是否会产生不一样的后果!!!

    0-12点

     

     

    那么我们把时间改为22点呢

    拦截成功

    不多BB,这个还是有问题,无法处理接口类问题

    动态字节码生成

    使用cblib

    package spring.aop.cglib;
    
    import java.lang.reflect.Method;
    import java.util.Date;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    import spring.aop.util.DateUtil;
    
    /**
     * 
     * Title: RequestCtrlCallback.java
     * Description: 动态字节码技术
     * @author xiaof
     * @date 2018年4月7日
     * @version 1.0 
     *
     */
    public class RequestCtrlCallback implements MethodInterceptor {
        
        private static final Log logger = LogFactory.getLog(RequestCtrlCallback.class);
    
        /**
         * 00:00:00
         */
        private String beginTime;
        /**
         * 00:00:00
         */
        private String endTime;
        
        
        
        public RequestCtrlCallback(String beginTime, String endTime) {
            this.beginTime = beginTime;
            this.endTime = endTime;
        }
    
    
    
        @Override
        public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
    
            //如果是我们需要拦截的方法,那么进行相应的操作
            if(arg1.getName().equals("request")) {
                if(DateUtil.isInDate(new Date(), beginTime, endTime)) {
                    //在对应的时间区间内,成功
                    logger.info("成功拦截到对应的区间,放行!");
                    return arg3.invokeSuper(arg0, arg2);
                } else {
                    logger.error("错误时间区间!!");
                    return null;
                }
            }
            
            return arg3.invokeSuper(arg0, arg2);
            
        }
    
    
    
        public String getBeginTime() {
            return beginTime;
        }
    
    
    
        public void setBeginTime(String beginTime) {
            this.beginTime = beginTime;
        }
    
    
    
        public String getEndTime() {
            return endTime;
        }
    
    
    
        public void setEndTime(String endTime) {
            this.endTime = endTime;
        }
    
    }
    package spring.aop.cglib;
    
    import org.junit.Test;
    import org.springframework.cglib.proxy.Enhancer;
    
    import spring.aop.designPattern.SubjectImpl;
    
    public class Main {
    
        @Test
        public void test1() {
            //使用cglib代理对象
            String beginTime = "00:00:00";
            String endTime = "20:00:00";
            Enhancer enhancer = new Enhancer();
            //设置代理类对象
            enhancer.setSuperclass(SubjectImpl.class);
            
            enhancer.setCallback(new RequestCtrlCallback(beginTime, endTime));
            
            //生成代理对象
            SubjectImpl proxyObj = (SubjectImpl) enhancer.create();
            
            proxyObj.request();
        }
    }

    结果展示:

  • 相关阅读:
    POJ 2752 Seek the Name, Seek the Fame
    POJ 2406 Power Strings
    KMP 算法总结
    SGU 275 To xor or not to xor
    hihocoder 1196 高斯消元.二
    hihoCoder 1195 高斯消元.一
    UvaLive 5026 Building Roads
    HDU 2196 computer
    Notions of Flow Networks and Flows
    C/C++代码中的笔误
  • 原文地址:https://www.cnblogs.com/cutter-point/p/8955139.html
Copyright © 2011-2022 走看看