代理设计模式9--使用AOP风格的代理模式

        代理模式归根结底,就是在操作真实对象的前后加入新的操作。通常的,在项目中,把业务逻辑代码与公共的事务进行分离。Spring中采用AOP来操作。下面开始介绍如何代理一个Controller类,为Controller加入额外的操作。

        第一步:首先是加入依赖包,cglib动态代理的包,Controller类不能为final类哦,因为这个报过一次错。

         <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.10</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.10</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.5</version>
        </dependency>

         第二步:编写我们自己的注解。注解的知识还得加强,我自己都写不好。Component是Spring的注解,表明这是一个bean。

import org.springframework.stereotype.Component;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_PARAMETER, ElementType.METHOD})
@Component
public @interface MyControllerLog {
    String description() default "";

    //操作类型,增删改查
    String methodType() default "";
}

        第三步:编写切面

import com.ssi.web.helper.annotation.MyControllerLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
public class MyAspect ...
 
    //定义一个后置返回通知,它表示在切点处  “干什么”
    @AfterReturning(value = "pointCutName()")
    public void adviceAfter(JoinPoint joinPoint){
        LOGGER.info("操作开始,当前执行的方法是:{}",joinPoint.getSignature().getName());
        //获取切点方法的方法签名
        final MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
        //获取切点方法的反射对象
        final Method targetMethod=methodSignature.getMethod();
        //获取方法上的注解对象
        MyControllerLog annotionEntity = targetMethod.getAnnotation(MyControllerLog.class);
        //拿到注解对象,并获取注解上的信息
        String type = annotionEntity.methodType();
        LOGGER.info("操作结束,本次操作类型:{}",type);
    }

    //定义一个切点,它表示 “在哪里” 添加通知
    //拦截带有MyControllerLog注解的方法
    @Pointcut(value = "@annotation(com.ssi.web.helper.annotation.MyControllerLog)")
    public void pointCutName() {
         throw new UnsupportedOperationException("不允许调用切点方法");
    }
}

 

    第四步:在SpringMVC的配置文件中配置AOP切面的相关信息,SpringBoot中暂时不用配置

    <!--注解式AOP,Spring会自动在JDK动态代理和CGLIB之间转换-->
    <aop:aspectj-autoproxy proxy-target-class="true"/>

        第五步:在Controller层上加入我们的注解

 /**
     * 去所有文章展示页面,这个是去博客空间的主页
     *
     * @return 携带上文章的参数,去文章首页
     */
    @RequestMapping(value = {URL_ARTICLE_LIST} ,method = {GET})
    @MyControllerLog(methodType = "查询")
    public ModelAndView home(HttpServletRequest request){
        LOGGER.info("enter article list page");
        //获取点击量最高的X篇文章
        final List<Article> hotArticles = articleService.getArticleByClick(5);
        ...其它逻辑代码
        return new ModelAndView(FWD_ARTICLE_LIST_HOME,map);
    }

     第六步:启动项目,并在控制台查看效果

    

       看注解,的却是加载了home()方法上。另外,一般这些操作都记录在数据库中。可以在切面类里面,加一个LogService,专门用来保存用户操作的数据。

 

分割线--------------------------------------------------------------------------------------------

下一篇:代理设计模式10知识扩展----注解与AOP

 

        

 

posted @ 2022-07-17 12:15  小大宇  阅读(34)  评论(0编辑  收藏  举报