Spring-5-AOP原理实现

AOP是通过动态代理实现的

1.JDK动态代理(有接口的情况):使用动态代理,创建接口实现类代理对象。
2.CGLIB动态代理(没有接口的情况):使用动态代理,创建类的子类代理对象。


一、JDK动态代理(有接口的情况)

JDK 动态代理是通过 JDK 中的 java.lang.reflect.Proxy 类实现的。

  1. 创建PersonService接口
    package com.seven.service;
    
    public interface PersonService {
        
        void add();
    
        void delete();
    
        void update();
    
        void findAll();
    }
    
  2. 创建PersonServiceImpl类,实现PersonService接口
    package com.seven.service.impl;
    
    import com.seven.service.PersonService;
    
    public class PersonServiceImpl implements PersonService {
        public void add() {
            System.out.println("增加---------------------");
        }
    
        public void delete() {
            System.out.println("删除---------------------");
        }
    
        public void update() {
            System.out.println("修改---------------------");
        }
    
        public void findAll() {
            System.out.println("查询---------------------");
        }
    }
    
  3. 创建LogAspect类,是一个切面类
    package com.seven.aspect;
    
    public class LogAspect {
    
        public void recordLog() {
            System.out.println("记录日志@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
        }
    }
    
  4. 创建ProxyBeanFactory类
    package com.seven.factory;
    
    import com.seven.aspect.LogAspect;
    import com.seven.service.PersonService;
    import com.seven.service.impl.PersonServiceImpl;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * 该工厂用来创建PersonService代理对象
     */
    public class ProxyBeanFactory {
    
        public PersonService getBean() {
            //获得被代理对象
            final PersonService personService = new PersonServiceImpl();
            //获得切面类实例
            final LogAspect logAspect = new LogAspect();
    
            //返回代理对象
            return (PersonService) Proxy.newProxyInstance(
                    ProxyBeanFactory.class.getClassLoader(),        //第一个参数,类加载器
                    new Class[]{PersonService.class},          		//第二个参数,被代理接口的Class对象,是个数组
                    new InvocationHandler() {                       //第三个参数,代理对象,该对象实现InvocationHandler接口,重写invoke方法
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            logAspect.recordLog();  //前置通知
                            Object object = method.invoke(personService, args);
                            logAspect.recordLog();  //后置通知
                            return object;
                        }
                    }
            );
        }
    }
    
  5. 测试类
    import com.seven.factory.ProxyBeanFactory;
    import com.seven.service.PersonService;
    import org.junit.Test;
    
    public class JDKProxyTest {
    
        @Test
        public void test() {
            //获取代理对象
            PersonService personService = new ProxyBeanFactory().getBean();
            //执行增加
            personService.add();
        }
    }
    

执行结果:
在这里插入图片描述

二、CGLIB动态代理(没有接口的情况)

CGLIB(Code Generation Library)是一个高性能开源的代码生成包,它被许多 AOP 框架所使用,其底层是通过使用一个小而快的字节码处理框架 ASM(Java 字节码操控框架)转换字节码并生成新的类。因此 CGLIB 要依赖于 ASM 的包。 Spring 的核心包 spring-core-3.2.2.RELEASE.jar中就有这个包。
在这里插入图片描述

  1. 创建PersonServiceImpl类
    package com.seven.service;
    
    public class PersonServiceImpl {
        public void add() {
            System.out.println("增加---------------------");
        }
    
        public void delete() {
            System.out.println("删除---------------------");
        }
    
        public void update() {
            System.out.println("修改---------------------");
        }
    
        public void findAll() {
            System.out.println("查询---------------------");
        }
    }
    
  2. 创建LogAspect类,是一个切面类
    package com.seven.aspect;
    
    public class LogAspect {
    
        public void recordLog() {
            System.out.println("记录日志@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
        }
    }
    
  3. 创建ProxyBeanFactory类
    package com.seven.factory;
    
    import com.seven.aspect.LogAspect;
    import com.seven.service.PersonServiceImpl;
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    /**
     * 该工厂用来创建PersonServiceImpl的代理对象
     */
    public class ProxyBeanFactory {
    
        public PersonServiceImpl getBean() {
            //获得被代理对象
            final PersonServiceImpl personServiceImpl = new PersonServiceImpl();
            //获得切面类实例
            final LogAspect logAspect = new LogAspect();
    
            //获得 CGLIB 的核心类 Enhancer
            Enhancer enhancer = new Enhancer();
            //设置要增强的类
            enhancer.setSuperclass(personServiceImpl.getClass());
            //设置回调函数
            //参数为一个Callback接口
            enhancer.setCallback(new MethodInterceptor() {
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    logAspect.recordLog();  //前置通知
                    Object object = method.invoke(personServiceImpl, objects);
                    logAspect.recordLog();  //后置通知
                    return object;
                }
            });
    
            //返回代理对象
            return (PersonServiceImpl) enhancer.create();
        }
    }
    
  4. 测试类
    import com.seven.factory.ProxyBeanFactory;
    import com.seven.service.PersonServiceImpl;
    import org.junit.Test;
    
    public class JDKProxyTest {
    
        @Test
        public void test() {
            //获取代理对象
            PersonServiceImpl personServiceImpl = new ProxyBeanFactory().getBean();
            //执行增加
            personServiceImpl.add();
            //执行删除
            personServiceImpl.delete();
            //执行修改
            personServiceImpl.update();
            //执行查询
            personServiceImpl.findAll();
        }
    }
    

执行结果:
在这里插入图片描述


更新时间:2020-1-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值