zoukankan      html  css  js  c++  java
  • springAOP原理以及概念

    需求:
    1、拦截所有业务方法
    2、判断用户是否有权限,有权限就让他执行业务方法,没有权限就不允许执行。(是否有权限是根据user是否为null作为判断依据)

    思考:

    我们该如何实现?

    思路1:

      我们在每个业务方法上面加上判断语句。

    否决掉了。代码过多,不灵活如果我需要更改需求就要挂掉。

    解决方式:

    使用动态代理实现。

    Proxy动态代理。要求:被代理的对象需要有父接口。

    准备代码:

    package cn.itcast.service;
    
    public interface PersonService {
        public abstract String getPersonName(Integer personId);
        public abstract void save(String name);
        public abstract void update(String name,Integer personId);
    }
    
    package cn.itcast.service.impl;
    
    import cn.itcast.service.PersonService;
    
    public class PersonServiceBean implements PersonService{
        private String user=null;
        
        public PersonServiceBean(){}
        
        public String getUser() {
            return user;
        }
    
        public PersonServiceBean(String user){
            this.user=user;
        }
        
        
        public String getPersonName(Integer personId) {
            System.out.println("我是getPersonName()方法");
            return "xxx";
        }
    
        
        public void save(String name) {
            System.out.println("我是save()方法");
        }
    
        
        public void update(String name, Integer personId) {
            System.out.println("我是update()方法");
        }
    
    }
    View Code

    Proxy代理:

    package cn.itcast.aop;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    import cn.itcast.service.impl.PersonServiceBean;
    
    public class JDKProxyFactory implements InvocationHandler{
        private Object targetObject;
        
        public Object createProxyInstance(Object targetObject){
            this.targetObject=targetObject;
            return     Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(), 
                    this.targetObject.getClass().getInterfaces(), this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {//环绕通知
            PersonServiceBean bean=(PersonServiceBean) targetObject;
            Object result=null;
            if(bean!=null && bean.getUser()!=null){
                try{
                    //...advice()-->前置通知
                    result=method.invoke(targetObject, args);
                    //...afteradvice()-->后置通知
                }catch(RuntimeException e){
                    //exceptionadvice()-->例外通知
                }finally{
                    //finallyadvice()-->最终通知
                }
                
            }
            return result;
        }
    }

    如果操作的目标对象没有父接口,应该怎么做呢?

    使用cglib.jar生成代理对象

    原理:

    生成的代理对象继承自原对象,重写了原对象的除了final外方法

    导入jar:

    cglib-nodep-2.1_3.jar

    主要代码:

    package cn.itcast.aop;
    
    import java.lang.reflect.Method;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    import cn.itcast.service.impl.PersonServiceBean;
    
    public class CGlibProxyFactory implements MethodInterceptor{
        private Object targetObject;
        
        public Object createProxyInstance(Object targetObject){
            this.targetObject=targetObject;
            Enhancer enhancer=new Enhancer();
            enhancer.setSuperclass(this.targetObject.getClass());//继承了目标类,对目标类里面所有非final方法进行和覆盖,在覆盖的方法内添加自身代码
            enhancer.setCallback(this);
            return enhancer.create();
        }
    
        @Override
        public Object intercept(Object proxy, Method method, Object[] args,
                MethodProxy methodProxy) throws Throwable {
            PersonServiceBean bean=(PersonServiceBean) targetObject;
            Object result=null;
            if(bean!=null && bean.getUser()!=null){
                result=method.invoke(targetObject, args);
            }
            return result;
        }
    }

    spring的AOP操作的内部原理就是使用的上面两种动态代理方式。

    现在讲讲AOP的一些概念:

    横切性关注点

    前面我们思考的拦截对象拦截方式等叫做横切性关注点。
    对什么进行拦截,拦截后应该做什么,这些思考的步骤,我们可以定义为横切性关注点。

    aspect(切面):
    指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类时对物体特征的抽象,而切面是横切性关注点的抽象。

    joinpoint(连接点)
    所谓连接点,就是指那些被拦截到的方法。在上面的例子中,练接点是绝大部分方法(非native),在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或者类构造器

    pointcut(切入点):
    所谓切入点,就是指的我们需要拦截的连接点的定义,在上面的例子中指的是业务方法

    advice(通知):拦截到连接点之后需要做的事

     

    public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {//环绕通知
            PersonServiceBean bean=(PersonServiceBean) targetObject;
            Object result=null;
            if(bean!=null && bean.getUser()!=null){
                try{
                    //...advice()-->前置通知
                    result=method.invoke(targetObject, args);
                    //...afteradvice()-->后置通知
                }catch(RuntimeException e){
                    //exceptionadvice()-->例外通知
                }finally{
                    //finallyadvice()-->最终通知
                }
                
            }
            return result;
        }

    target(目标对象):

    代理的目标对象

    weave(织入):
    将aspects应用到target对象并导致proxy对象创建的过程称为织入

    introduction(引入):
    在不修改类代码的前提下,Introduction可以在运行期为类动态地添加一些方法或者Field

  • 相关阅读:
    TSQL(3)批处理
    TSQL(5)操作数据行
    如何设计数据库(1)?
    搜索引擎处理查询
    如何进行shell脚本正确性测试
    机房收费系统用户级别查询
    PageRank算法
    链接分析算法之:SALSA算法
    机器学习排序
    倒排索引搜索引擎的基石
  • 原文地址:https://www.cnblogs.com/aigeileshei/p/5913122.html
Copyright © 2011-2022 走看看