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;
    }
}
 

猜你喜欢

转载自www.cnblogs.com/wangfeixiong/p/8980060.html