zoukankan      html  css  js  c++  java
  • SpringBoot使用AOP(动态代理)

    SpringBoot使用AOP(动态代理)

    • cgllib 需要添加依赖
    <!--cglib动态代理-->
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.2.12</version>
    </dependency>
    <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-aop</artifactId>
          <version>2.1.7.RELEASE</version>
      </dependency>
    1. 目标target(需要被增强的接口)
    //目标target
    public interface UserService {
        void login(String username, String password);
        void regist();
        void search();
        void update();
    }
    1. 接口实现
    /**
     * @Description
     * @Author zhoumm
     * @Version V1.0.0
     * @Since 1.0
     * @Date 2019-08-24
     */
    @Service
    public class UserServiceImpl implements UserService{
        @Override
        public void login(String username, String password) {
            System.out.println ("登录");
        }
    
        @Override
        public void regist() {
            System.out.println ("注册");
        }
    
        @Override
        public void search() {
            System.out.println ("userService search...");
        }
    
        @Override
        public void update() {
            System.out.println ("update...");
        }
    }
    1. 代理增强类
    /**
     * @Description  代理增强类
     * @Author 
     * @Version V1.0.0
     * @Since 1.0
     * @Date 2019-08-25
     */
    @Component
    @Aspect  //标识为一个切面供容器读取
    public class UserServiceHelper {
        @Before("execution(* com.mmz.tkp.controller.aoptest.UserService.s*(..))")
        public void before(){
            System.out.println ("前置通知。。。");
        }
    
        @AfterReturning(value="execution(* com.mmz.tkp.controller.aoptest.UserService.s*(..))")
        public void afterReturning(){
            System.out.println ("后置通知。。。");
        }
    
        @Around("execution(* com.mmz.tkp.controller.aoptest.UserService.s*(..))")
        public void around(ProceedingJoinPoint pjp) throws Throwable {
            System.out.println ("环绕前。。。");
            Object value = pjp.proceed();
            System.out.println (value);
            System.out.println ("环绕后。。。");
        }
    
        @After("execution(* com.mmz.tkp.controller.aoptest.UserService.s*(..))")
        public void after(){
            System.out.println ("最终通知。。。");
        }
    
        @AfterThrowing(value="execution(* *.s*(..))",throwing="ex")
        public void afterThrowing(JoinPoint jp,Throwable ex){
            System.out.println ("异常抛出通知" + ex);
        }
    
        @Pointcut("execution(* com.mmz.tkp.controller.aoptest.UserService.search(..))")
        public void mypointcut(){}
    
        @Pointcut("execution(* com.mmz.tkp.controller.aoptest.UserService.update(..))")
        public void mypointcut1(){}
    
        //使用@Pointcut来声明切点,避免在每个通知中定义切点
        @Before("mypointcut()||mypointcut1()")
        public void before1(){
            System.out.println ("前置通知。。。。");
        }
    }
    1. JDK动态代理工厂类
    /**
     * @Description JDK动态代理工厂类
     * 在运行期 ,在JVM内部动态生成class字节码对象(Class对象)
     * Jdk动态代理只针对于接口操作
     * @Author 
     * @Version V1.0.0
     * @Since 1.0
     * @Date 2019-08-24
     */
    public class JDKProxyFactory implements InvocationHandler {
        //目标对象
        private Object target;
    
        public JDKProxyFactory(Object target) {
            this.target = target;
        }
    
        //使用Proxy创建代理对象
        public Object createProxy(){
            //目标类的类加载器对象
            ClassLoader classLoader = target.getClass().getClassLoader();
            //目标类的实现接口的Class[]
            Class<?>[] interfaces = target.getClass().getInterfaces();
            //当前对象需实现InvocationHandler接口
            return Proxy.newProxyInstance(classLoader,interfaces,this);
        }
    
        /**
         *
         * @param proxy  代理对象,一般不用
         * @param method 方法对象
         * @param args  方法参数
         * @return
         * @throws Throwable
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //在调用目标对象方法前,统一做一些其他操作,即功能增强
            System.out.println ("例如:日志操作......");
            return method.invoke(target,args);
        }
    }
    1. CGLIB动态代理
    /**
     * @Description  CGLIB动态代理
     * CGLIB(Code Generation Library)是一个开源项目
     * 是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。
     * CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类
     *
     * 可以为没有实现接口的类去做代理,也可以为实现接口的类去做代理。
     *
     * spring采用的是哪一种动态机制:
     *     如果目标对象,有接口,优先使用jdk动态代理
     *     如果目标对象,无接口,使用cglib动态代理。
     * @Author zhoumm
     * @Version V1.0.0
     * @Since 1.0
     * @Date 2019-08-24
     */
    public class CglibProxyFactory implements MethodInterceptor {
        //目标对象
        private Object target;
    
        public CglibProxyFactory(Object target) {
            this.target = target;
        }
    
        //创建代理对象
        public Object createProxy(){
            //1.创建Enhancer
            Enhancer enhancer = new Enhancer();
            //2.传递目标对象Class
            enhancer.setSuperclass(target.getClass());
            //3.设置回调操作(相当于InvocationHandler)
            enhancer.setCallback(this);
    
            return enhancer.create();
        }
    
    
        @Override
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            //在调用目标对象方法前,统一做一些其他操作,即功能增强
            System.out.println ("例如:日志操作......");
            return method.invoke(target,args);
        }
    }
    1. controller 代理测试
    @Api(value = "aop", description = "面向切面编程")
    @RestController
    @RequestMapping("/kpt/aop")
    @Slf4j
    @Validated
    public class AopBackGroundController {
    
        @Autowired
        private UserService userService;
    
        @ApiOperation(value = "JDK动态代理测试", httpMethod = "GET")
        @RequestMapping(value = "/jdkproxy", method = RequestMethod.GET)
        public void testJDKProxy(){
            //JDK动态代理
            userService.login("zz","123456");
            System.out.println ("--------------JDK动态代理------------");
            JDKProxyFactory jdkProxyFactory = new JDKProxyFactory(userService);
            UserService userServiceProxy = (UserService)jdkProxyFactory.createProxy();
            userServiceProxy.login("zz","123456");
        }
    
        @ApiOperation(value = "CGLIB动态代理测试", httpMethod = "GET")
        @RequestMapping(value = "/cglibproxy", method = RequestMethod.GET)
        public void testCGLIBProxy(){
            //CGLIB动态代理
            userService.regist();
            System.out.println ("--------------CGLIB动态代理------------");
            CglibProxyFactory cglibProxyFactory = new CglibProxyFactory(userService);
            UserService userServiceProxy = (UserService)cglibProxyFactory.createProxy();
            userServiceProxy.regist();
        }
    
        @ApiOperation(value = "AspectJ代理测试", httpMethod = "GET")
        @RequestMapping(value = "/aspectJproxy", method = RequestMethod.GET)
        public void testAspectJ(){
            //com.mmz.tkp.controller.aoptest.UserServiceHelper
            userService.search();
        }
    
        @ApiOperation(value = "切点通知测试", httpMethod = "GET")
        @RequestMapping(value = "/aspectJproxy", method = RequestMethod.GET)
        public void testPointcutAdvice(){
            //com.mmz.tkp.controller.aoptest.UserServiceHelper
            userService.search();
        }
    }
  • 相关阅读:
    关于ActionScript中那些你不知道的事情
    Flash Player 11 Stage3D学习大杂烩
    Qt 控制台输入输出(支持中文)
    Redis消息发布订阅的稳定性验证结论
    C++11 Lambda表达式(匿名函数)用法详解
    vue中“:”、“.”、“@”意义
    QT中printf输出不同步的解决办法
    QT5中使用SQLite
    QT 调用user32.dll移动鼠标
    10分钟学会Visual Studio将自己创建的类库打包到NuGet进行引用(net,net core,C#)
  • 原文地址:https://www.cnblogs.com/yuluoxingkong/p/13449351.html
Copyright © 2011-2022 走看看