软件工程应用与实践(7)——业务逻辑层之 AOP 面向切面编程(2)

本文介绍了如何在Spring中使用AOP进行业务逻辑增强,包括定义业务接口、创建接口实现类、定义切面类并配置切点,以及注册AspectJ的自动代理。示例展示了在医疗服务场景中,如何通过切面实现日志记录,增强了服务的安全性和可追溯性。
摘要由CSDN通过智能技术生成

2021SC@SDUSC

一、实现步骤

1,定义业务接口

JDK 代理 : 基于接口的动态代理技术
目标对象必须要有接口,代理对象通过接口动态生成的

package service;

public interface Service
{
	public void run();
}

2,创建业务接口实现类

package service.impl;

public class ServiceImpl implements Service{
	public void run(){
		System.out.println("begin run!");
	}
}

3,定义切面类

类中定义了若干普通方法,将作为不同的通知方法,用来增强功能。

package aspect;

@Aspect
public class MyAspect{
	@Before(value = "execution(* run(..))")//所有的run方法前执行
    public void myBefore(){
        //就是你切面要执行的功能代码
        System.out.println("前置通知, 切面功能:在目标方法之前输出执行时间:"+ new Date());
    }
}

4,声明目标对象切面类对象

<!--声明目标类对象-->
<bean id="ServiceTarget" class="service.impl.ServiceImpl”/>
<!--声明切面类对象-->
<bean id="myAspect" class="aspect.MyAspect"/>

5,注册 AspectJ 的自动代理

<!--声明自动代理生成器-->
<aop:aspectj-autoproxy/>

在定义好切面 Aspect 后,需要通知 Spring 容器,让容器生成“目标类+ 切面”的代理对象。这个代理是由容器自动生成的。只需要在 Spring 配置文件中注册一个基于 aspectj 的自动代理生成器,其就会自动扫描到@Aspect 注解,并按通知类型与切入点,将其织入,并生成代理。
aop:aspectj-autoproxy/的底层是由AnnotationAwareAspectJAutoProxyCreator 实现的。从其类名就可看出,是基于 AspectJ 的注解适配自动代理生成器。
其工作原理是,aop:aspectj-autoproxy/通过扫描找到@Aspect 定义的切面类,再由切面类根据切入点找到目标类的目标方法,再由通知类型找到切入的时间点。

二、本项目的具体实现

1,业务接口

package com.sdu.nurse.service;

import com.sdu.nurse.entity.TreeData;

import java.util.List;

public interface TreeDataService
{
    //获取所有树的节点及其子节点
    List<TreeData> getAllTreeNodes();
    //获取一级名称
    List<TreeData> getFirstNodes();
    //获取一级名称对应的二级名称
    List<TreeData> getSecondNodes(String firstNodeName);
    //获取二级名称对应的三级名称
    List<TreeData> getThirdNodes(String secondNodeName);
    //获取三级名称对应的四级名称
    List<TreeData> getFourthNodes(String thirdNodeName);
}

2,创建业务接口实现类

package com.sdu.nurse.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sdu.nurse.dao.TreeDataDao;
import com.sdu.nurse.entity.TreeData;
import com.sdu.nurse.service.TreeDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
@Transactional
public class TreeDateServiceImpl implements TreeDataService
{
    @Autowired
    private TreeDataDao treeDataDao;

    @Override
    public List<TreeData> getAllTreeNodes() {
        //获取一级节点
        List<TreeData> healthTreeNodes = getFirstNodes();
        //设置二级节点
        healthTreeNodes.forEach(healthTreeNode->{
            healthTreeNode.setChildren(getSecondNodes(healthTreeNode.getLabel()));
        });
        //设置三级节点
        healthTreeNodes.forEach(healthTreeNode->{
            healthTreeNode.getChildren().forEach(second->{
                second.setChildren(getThirdNodes(second.getLabel()));
            });
        });
        //设置四级节点
        healthTreeNodes.forEach(healthTreeNode->{
            healthTreeNode.getChildren().forEach(second->{
                second.getChildren().forEach(third->{
                    third.setChildren(getFourthNodes(third.getLabel()));
                });
            });
        });
        return healthTreeNodes;
    }

    @Override
    public List<TreeData> getFirstNodes() {
        return treeDataDao.getAllFirstNodes();
    }

    @Override
    public List<TreeData> getSecondNodes(String firstNodeName) {
        return treeDataDao.getAllSecondNodes(firstNodeName);
    }

    @Override
    public List<TreeData> getThirdNodes(String secondNodeName) {
        return treeDataDao.getAllThirdNodes(secondNodeName);
    }

    @Override
    public List<TreeData> getFourthNodes(String thirdNodeName) {
        return treeDataDao.getALlFourthNodes(thirdNodeName);
    }
}

3,定义切面类

package com.stuPayment.util;

import java.util.Arrays;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Aspect
@Component
public class WebLogAspect {
    
    private final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
    
    @Pointcut("execution(public * com.sdu.nurse.service..*.*(..))")//切入点描述 这个是controller包的切入点
    public void controllerLog(){}//签名,可以理解成这个切入点的一个名称
    
    @Pointcut("execution(public * com.sdu.nurse.service..*.*(..))")//切入点描述,这个是uiController包的切入点
    public void uiControllerLog(){}
    @Before("controllerLog() || uiControllerLog()") //在切入点的方法run之前要干的
    public void logBeforeController(JoinPoint joinPoint) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();//这个RequestContextHolder是Springmvc提供来获得请求的东西
        HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
        
         // 记录下请求内容
        logger.info("################URL : " + request.getRequestURL().toString());
        logger.info("################HTTP_METHOD : " + request.getMethod());
        logger.info("################IP : " + request.getRemoteAddr());
        logger.info("################THE ARGS OF THE CONTROLLER : " + Arrays.toString(joinPoint.getArgs())); 
        logger.info("################CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值