美文网首页
Spring AOP

Spring AOP

作者: 磊_5d71 | 来源:发表于2018-10-19 17:17 被阅读0次

    AOP简介

    • AOP Aspect Oriented Programing 面向切面编程
    • AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(如性能监视、事务管理、安全检查、缓存等)
    • AOP横向抽取与传统纵向继承对比图


      图片.png
    • Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码。

    AOP相关术语

    • Joinpoint(连接点):所谓的连接点是指那些被拦截到的点。在Spring中,这些点指的是方法,Spring只支持方法类型的连接点。
    • Pointcut(切入点):所谓的切入点是指我们要对哪些Joinpoint进行拦截的定义。
    • Advice(通知/增强):所谓通知是指拦截到Joinpoint之后要做的事情就是通知。通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)。
    • Introduction(引介):引介是一种特殊的通知,在不修改类代码的前提下,在运行期为类动态地添加一些方法或Field。
    • Target(目标对象):代理的目标对象
    • Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。Spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。
    • Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类。
    • Aspect(切面):是切入点和通知(引介)的结合。


      图片.png

    AOP底层实现:JDk的动态代理

    只能对实现了接口的类进行动态代理

    • UserDao接口
    package com.alan.aop.demo1;
    
    public interface UserDao {
    
        public void save();
    
        public void uodate();
    
        public void delete();
    
        public void find();
    }
    
    • UserDaoImpl实现类
    package com.alan.aop.demo1;
    
    public class UserDaoImpl implements  UserDao {
    
    
        @Override
        public void save() {
    
            System.out.println("保存用户。。。");
        }
    
        @Override
        public void uodate() {
            System.out.println("修改用户。。。");
        }
    
        @Override
        public void delete() {
            System.out.println("删除用户。。。");
    
        }
    
        @Override
        public void find() {
            System.out.println("查询用户。。。");
    
        }
    }
    
    • 代理类
    package com.alan.aop.demo1;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * UserDao代理类
     */
    public class MyJdkProxy implements InvocationHandler {
    
        private UserDao userDao;
    
        //通过构造方法传入要代理的类
        public MyJdkProxy(UserDao userDao){
            this.userDao = userDao;
        }
    
        //产生代理类(对实现接口类产生代理)
        public Object createProxy(){
    
            //需要传入三个参数:类的加载器、类实现的接口、InvocationHandler接口
            Object proxy = Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(),this);
            return proxy;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            if("save".equals(method.getName())){
                System.out.println("权限校验。。。");
                return method.invoke(userDao,args);
            }
            return method.invoke(userDao,args);
        }
    }
    
    • 测试类
    package com.alan.aop.demo1;
    
    import org.junit.Test;
    
    public class SpringDemo1 {
    
        @Test
        public void demo1(){
    
            UserDao userDao = new UserDaoImpl();
    
    
            //创建代理
            UserDao proxy = (UserDao) new MyJdkProxy(userDao).createProxy();
    
            proxy.save();
            proxy.uodate();
            proxy.delete();
            proxy.find();
        }
    }
    

    AOP的底层实现:CGLIB的动态代理

    • 对于不使用接口的业务类,无法使用JDK动态代理
    • CGLIB采用非常底层字节码技术,可以为一个类创建子类,解决无接口代理问题
    • 实体类
    package com.alan.aop.demo2;
    
    public class ProductDao {
    
    
       public void save() {
    
           System.out.println("保存用户。。。");
       }
    
       public void uodate() {
           System.out.println("修改用户。。。");
       }
    
       public void delete() {
           System.out.println("删除用户。。。");
    
       }
    
       public void find() {
           System.out.println("查询用户。。。");
    
       }
    }
    
    • 代理类
    package com.alan.aop.demo2;
    
    import com.alan.aop.demo1.MyJdkProxy;
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    public class MyCglibProxy implements MethodInterceptor {
    
    
        private ProductDao productDao;
    
    
        //构造方法传入ProductDao对象
        public MyCglibProxy(ProductDao productDao){
            this.productDao = productDao;
        }
    
    
        //创建方法生成代理
        public  Object createProxy(){
            //1、创建核心类
            Enhancer enhancer = new Enhancer();
            //2、设置父类
            enhancer.setSuperclass(productDao.getClass());
            //3、设置回调(this代表当前对象,对实现接口的调用)
            enhancer.setCallback(this);
            //4、生成代理
            Object proxy = enhancer.create();
            return proxy;
    }
    
        @Override
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    
            if("save".equals(method.getName())){
                System.out.println("用户校验。。。。");
                return  methodProxy.invokeSuper(proxy,args);
            }
    
            //invokeSuper调用父类的方法
            return methodProxy.invokeSuper(proxy,args);
        }
    }
    
    • 测试类
    package com.alan.aop.demo2;
    
    import org.junit.Test;
    
    public class SpringDemo2 {
    
    
    
        @Test
        public void demo1(){
    
            ProductDao productDao = new ProductDao();
    
            ProductDao proxy = (ProductDao) new MyCglibProxy(productDao).createProxy();
    
            proxy.delete();
            proxy.find();
            proxy.save();
            proxy.uodate();
        }
    }
    

    Spring代理实现

    图片.png
    图片.png

    Spring AOP增强类型

    图片.png 图片.png

    Spring AOP切面类型

    图片.png
    • StudentDao接口类
    package com.alan.aop.demo3;
    
    public interface StudentDao {
    
        public void save();
    
        public void update();
    
        public void delete();
    
        public void find();
    }
    
    • StudentDaoImpl接口实现类
    package com.alan.aop.demo3;
    
    public class StudentDaoImpl implements StudentDao {
    
    
        @Override
        public void save() {
            System.out.println("学生保存。。。");
    
        }
    
        @Override
        public void update() {
            System.out.println("学生修改。。。");
    
        }
    
        @Override
        public void delete() {
            System.out.println("学生保存。。。");
    
        }
    
        @Override
        public void find() {
            System.out.println("学生查询。。。");
    
        }
    }
    
    • 测试类
    package com.alan.aop.demo3;
    
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import javax.annotation.Resources;
    
    
    //通过注解简化测试。不需要在代码中通过ApplicationContext对象进行xml配置了
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class SpringDemo3 {
    
    
        @Autowired
        @Qualifier("studentDaoProxy")
        private StudentDao studentDao;
    
        @Test
        public void demo1(){
            studentDao.delete();
            studentDao.find();
            studentDao.save();
            studentDao.update();
        }
    
    }
    
    • xml配饰文件
        <!--前置通知类型===================-->
        <bean id="myBeforeAdvice" class="com.alan.aop.demo3.MyBeforeAdvice"></bean>
        <!--Spring AOP产生代理对象-->
        <bean id="studentDaoProxy"  class="org.springframework.aop.framework.ProxyFactoryBean">
            <!--配置目标类-->
            <property name="target" ref="studentDao"></property>
            <!--配置要实现的接口-->
            <property name="proxyInterfaces" value="com.alan.aop.demo3.StudentDao"></property>
            <!--配置增强类型,采用拦截的名称-->
            <property name="interceptorNames" value="myBeforeAdvice"></property>
    
        </bean>
    
    • MyBeforeAdvice增强实现类
    package com.alan.aop.demo3;
    
    import org.springframework.aop.MethodBeforeAdvice;
    
    import java.lang.reflect.Method;
    
    public class MyBeforeAdvice implements MethodBeforeAdvice {
        @Override
        public void before(Method method, Object[] objects, Object o) throws Throwable {
            System.out.println("前置增强。。。。");
        }
    }
    

    Spring带有切入点的切面配置案例(demo5)

    图片.png

    自动代理创建(demo6)

    图片.png

    Spring的传统AOP的基于切面信息的自动代理

    相关文章

      网友评论

          本文标题:Spring AOP

          本文链接:https://www.haomeiwen.com/subject/styqzftx.html