zoukankan      html  css  js  c++  java
  • Spring-AOP 基于注解的实现

    一、AOP:

    是对OOP编程方式的一种补充。翻译过来为“面向切面编程”。

    可以理解为一个拦截器框架,但是这个拦截器会非常武断,如果它拦截一个类,那么它就会拦截这个类中的所有方法。如对一个目标列的代理,增强了目标类的所有方法。

    两个解决办法:

    1.不优雅的做法:

    在添加增强时,根据方法名去判断,是否添加增强,但是这样就得一直去维护这个增强类。

    2.面向切面:

    将增强类和拦截条件组合在一起,然后将这个切面配置到 ProxyFactory 中,从而生成代理。

    二、AOP 和 切面的关系

    1.类比于 OOP 和 对象,AOP 和 切面就是这样的一种关系。

    2.也可以将 切面 看成是 AOP 的一个工具。

    三、几个概念

    切面(Advisor):是AOP中的一个术语,表示从业务逻辑中分离出来的横切逻辑,比如性能监控,日志记录,权限控制等。

    这些功能都可以从核心的业务逻辑中抽离出去。可以解决代码耦合问题,职责更加单一。封装了增强和切点。

    增强(Advice):增强代码的功能的类,横切到代码中。

    目标:目标方法(JDK代理)或目标类(CGLIB代理)

    代理:JDK代理,CGLIB代理。或是通过 ProxyFactory 类生产。

    切点:通过一个条件来匹配要拦截的类,这个条件称为切点。如拦截所有带 Controller 注解的类。增强的条件。

    连接点:作为增强方法的入参,可以获取到目标方法的信息。

    四、实践:自定义一个注解,用Spring-AOP实现给添加这个注解的方法做业务处理

    1.POM文件中引入Spring的jar包,其他jar不需要引用。

            <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aop</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
                <version>${spring.version}</version>
            </dependency>

    2.自定义一个注解

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     *  监控请求的进度
     *  @author  wangfeixiong
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ReviewProgressAnnotation {
        String value();
    }

    3.配置Spring 开启AOP注解

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:task="http://www.springframework.org/schema/task"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
           http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd ">
    
        <description>Spring MVC Configuration</description>
    
        <!-- 加载配置属性文件 -->
        <context:property-placeholder ignore-unresolvable="true" location="classpath:*.properties"/>
        
        <!-- 使用Annotation自动注册Bean -->
        <context:component-scan base-package="com.future.dcwj"/>
        <!-- 默认的注解映射的支持,org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping -->
        <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
            <mvc:message-converters register-defaults="true">
                <!-- 将StringHttpMessageConverter的默认编码设为UTF-8 -->
                <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                    <constructor-arg value="UTF-8"/>
                </bean>
            </mvc:message-converters>
        </mvc:annotation-driven>
        
        <!--开启spring中的定时任务-->
        <task:annotation-driven/>
        
        <!--开始AOP-->
        <aop:aspectj-autoproxy/>    
        
    
        <!-- 对静态资源文件的访问, 将无法mapping到Controller的path交给default servlet handler处理 -->
        <mvc:default-servlet-handler/>
    
        <!-- 静态资源映射 -->
        <mvc:resources mapping="/static/**" location="/static/" cache-period="31536000"/>
    
        <!-- 定义无Controller的path<->view直接映射 -->
        <mvc:view-controller path="/" view-name="redirect:${web.view.index}"/>
    </beans>

    4.书写注解类,自定义业务

    import com.future.dcwj.common.annotation.ReviewProgressAnnotation;
    import org.apache.log4j.Logger;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.stereotype.Component;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * describe:
     *
     * @author wangfeixiong
     * @date 2018/02/09
     */
    @Component
    @Aspect
    public class ReviewProgressAOP {
        private final static Logger LOGGER = Logger.getLogger(ReviewProgressAOP.class);
    
        public static final String SUCESS = "true";
        private static final String NO_SUCESS = "false";
        public static final String  REVIEW_ACTION_PROGRESS= "reviewActionProgress";
    
    
    
        @Pointcut("@annotation(com.future.dcwj.common.annotation.ReviewProgressAnnotation)")
        public void pointcutName() {
        }
    
    
        /**
         * @param joinPoint
         */
        @Around("pointcutName()")
        public Object introcepter(ProceedingJoinPoint joinPoint) {
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            ReviewProgressAnnotation progressAnnotation = methodSignature.getMethod().getAnnotation(ReviewProgressAnnotation.class);
            String operation = progressAnnotation.value();
            StringBuffer key = new StringBuffer();
            LOGGER.error(key.toString());
            User user = UserUtils.getUser();
            if (user != null) {
                key.append(user.getId());
            }
            key = key.append(operation);
            LOGGER.info(operation);
            try {
                Object result = joinPoint.proceed();
                map.put(key.toString(), SUCESS);
                JedisUtils.mapPut(REVIEW_ACTION_PROGRESS,map);
                return result;
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            return null;
        }
    }
     
  • 相关阅读:
    【凸优化】【长链剖分】【2019冬令营模拟1.8】tree
    2019冬令营集训1月7-10日总结
    item()方法遍历字典
    contiue和break的用法
    内存地址与变量值的关系
    Python垃圾回收机制
    Python的小整数池
    常量的命名和注意事项
    基本运算符
    Python中最简单快捷的输出方式
  • 原文地址:https://www.cnblogs.com/wangfeixiong/p/8980060.html
Copyright © 2011-2022 走看看