精华内容
下载资源
问答
  • 在进入实例之前,可以先看我引用的另一篇文章:一.... 创建AOP切面类,直接上代码这里为了简单明了,我将切面类分为普通类方法切面和自定义注解方法切面1.普通类方法切面类package com.example.demo.aop;import l...

    在进入实例之前,可以先看我引用的另一篇文章:

    一.   SpringBoot引入AOP依赖

    引入依赖:

    org.springframework.boot

    spring-boot-starter-aop

    二.    创建AOP切面类,直接上代码

    这里为了简单明了,我将切面类分为普通类方法切面和自定义注解方法切面

    1.    普通类方法切面类

    package com.example.demo.aop;

    import lombok.extern.slf4j.Slf4j;

    import org.aspectj.lang.JoinPoint;

    import org.aspectj.lang.annotation.*;

    import org.springframework.stereotype.Component;

    import java.util.Arrays;

    import java.util.List;

    /**

    * @program: demo

    * @description: 描述UserService切面类

    * @author: guoxu

    * @create: 2019-12-23 14:22

    */

    @Slf4j

    @Aspect

    @Component

    public class AopUserServiceAspect {

    /**

    * 1.通配符

    * [*] 匹配任意字符,但只能匹配一个元素

    * [..] 匹配任意字符,可以匹配任意多个元素,表示类时,必须和*联合使用

    * [+] 必须跟在类名后面,如Horseman+,表示类本身和继承或扩展指定类的所有类

    * 切点表达式分为 修饰符 返回类型 包路径 方法名 参数

    * 2.切点表达式

    * 3.逻辑运算符

    * 表达式可由多个切点函数通过逻辑运算组成

    * && 与操作,求交集,也可以写成and

    * 例如 execution(* chop(..)) && target(Horseman) 表示Horseman及其子类的chop方法

    * || 或操作,任一表达式成立即为true,也可以写成 or

    * 例如 execution(* chop(..)) || args(String) 表示名称为chop的方法或者有一个String型参数的方法

    * ! 非操作,表达式为false则结果为true,也可以写成 not

    * 例如 execution(* chop(..)) and !args(String) 表示名称为chop的方法但是不能是只有一个String型参数的方法

    */

    /**

    * 切点为UserServiceImpl类下的queryUser方法

    * "execution(* com.example.demo.service.impl.UserServiceImpl.queryUser())"

    *

    * 切点为UserServiceImpl类下的所有带任意参数的方法

    */

    @Pointcut("execution(* com.example.demo.service.impl.UserServiceImpl.*(..))")

    public void userServicePoc(){

    }

    /**

    * 环绕通知在 target 开始和结束执行

    * 如果在环绕通知方法中有异常捕获,则会直接捕获异常,不会再向外抛出

    * @param point

    * @return

    */

    // @Around(value = "userServicePoc()")

    // public Object around(ProceedingJoinPoint point) {

    // long start = System.currentTimeMillis();

    // //获取切点执行的方法

    // String methodName = point.getSignature().getName();

    // log.info("around method name: {} params: {}", methodName, Arrays.asList(point.getArgs()));

    // try {

    // log.info("around end time: {}", (System.currentTimeMillis() - start) + " ms!");

    // return point.proceed();

    // } catch (Throwable e) {

    // log.error("message: {}", e.getMessage());

    // }

    // return null;

    // }

    /**

    * * 前置通知在 target 前执行

    * @param joinPoint

    */

    // @Before("@annotation(com.leone.boot.aop.anno.AopBefore)")

    // @Before("within(com.leone.boot.aop.controller.*)")

    // @Before("@within(org.springframework.web.bind.annotation.RestController)")

    // @Before("target(com.leone.boot.aop.controller.UserController)")

    @Before(value = "userServicePoc()")

    public void beforeMethod(JoinPoint joinPoint) {

    String methodName = joinPoint.getSignature().getName();

    List args = Arrays.asList(joinPoint.getArgs());

    log.info("before inform method name: {} param: {}", methodName, args);

    }

    /**

    * 后置通知在target后执行

    *

    * @param joinPoint

    */

    //@After("@args(org.springframework.stereotype.Component) &&execution(* com.leone.boot.aop.controller.*.*(..))")

    @After(value = "userServicePoc()")

    public void afterMethod(JoinPoint joinPoint) {

    String methodName = joinPoint.getSignature().getName();

    List args = Arrays.asList(joinPoint.getArgs());

    log.info("after inform method name : {} param: {}", methodName, args);

    }

    /**

    * 在target执行成功返回后执行

    *

    * @param joinPoint

    * @param result

    */

    //@AfterReturning(value = "within(com.leone.boot.aop.controller.*)", returning = "result")

    @AfterReturning(value = "userServicePoc()",returning = "result")

    public void afterReturning(JoinPoint joinPoint, Object result) {

    String methodName = joinPoint.getSignature().getName();

    log.info("afterReturning inform method name: {} return value: {}", methodName, result);

    }

    /**

    * 在target抛出异常后执行

    *

    * @param joinPoint

    * @param ex

    */

    //@AfterThrowing(value = "args(com.leone.boot.common.entity.User) &&execution(* com.leone.boot.aop.controller.*.*(..))", throwing = "ex")

    @AfterThrowing(value = "userServicePoc()",throwing = "ex")

    public void afterThrowing(JoinPoint joinPoint, Exception ex) {

    String methodName = joinPoint.getSignature().getName();

    log.info("afterThrowing inform method name: {} exceptions: {}",methodName, ex);

    }

    }

    2.    自定义注解方法切面类

    1.    自定义注解

    package com.example.demo.aop;

    import java.lang.annotation.*;

    /**

    * 自定义注解,拦截service

    * 注解@Target说明了Annotation所修饰的对象范围

    *

    * 注解@Retention定义了该Annotation被保留的时间长短:

    * 1.SOURCE:在源文件中有效(即源文件保留)

    * 2.CLASS:在class文件中有效(即class保留)

    * 3.RUNTIME:在运行时有效(即运行时保留)

    *

    * 注解@Documented 定义注解会被javadoc或者其他类似工具文档化

    * @author guoxu

    */

    //自定义注解描述方法

    @Target({ElementType.PARAMETER, ElementType.METHOD})

    @Retention(RetentionPolicy.RUNTIME)

    @Documented

    public @interface SystemServiceLog {

    /**

    * 自定义注解参数

    */

    String description() default "";

    }

    2.    自定义切面类

    package com.example.demo.aop;

    import com.example.demo.controller.UserController;

    import com.example.demo.service.impl.UserServiceImpl;

    import lombok.extern.slf4j.Slf4j;

    import org.aspectj.lang.JoinPoint;

    import org.aspectj.lang.annotation.After;

    import org.aspectj.lang.annotation.Aspect;

    import org.aspectj.lang.annotation.Pointcut;

    import org.springframework.stereotype.Component;

    import java.util.Arrays;

    import java.util.List;

    /**

    * @program: demo

    * @description: 描述自定义注解切面类

    * @author: guoxu

    * @create: 2019-12-23 14:22

    */

    @Slf4j

    @Aspect

    @Component

    public class AopAnnotationAspect {

    private static String userService = UserServiceImpl.class.getName();

    private static String userController = UserController.class.getName();

    /**

    * 自定义注解Controller层切点

    */

    @Pointcut("@annotation(SystemControllerLog)")

    public void annoControllerPointCut() {}

    /**

    * 自定义注解Service层切点

    */

    @Pointcut("@annotation(SystemServiceLog)")

    public void annoServicePointCut() {}

    @After("annoServicePointCut()")

    public void afterServiceMethod(JoinPoint joinPoint){

    //获取拦截到执行的方法名称

    String methodName = joinPoint.getSignature().getName();

    // 获取拦截到操作的service类名

    String targetName = joinPoint.getTarget().getClass().getName();

    //获取切点方法的参数列表

    List args = Arrays.asList(joinPoint.getArgs());

    log.info("自定义注解SystemServiceLog切点方法->{},方法参数->{}",methodName,args);

    if (targetName.equals(userService)){

    log.info("UserServiceImpl切点方法->{},方法参数->{}",methodName,args);

    }

    }

    @After("annoControllerPointCut()")

    public void afterControllerMethod(JoinPoint joinPoint){

    //获取拦截到执行的方法名称

    String methodName = joinPoint.getSignature().getName();

    // 获取拦截到操作的service类名

    String targetName = joinPoint.getTarget().getClass().getName();

    //获取切点方法的参数列表

    List args = Arrays.asList(joinPoint.getArgs());

    if (targetName.equals(userController)){

    log.info("自定义注解SystemControllerLog切点方法->{},方法参数->{}",methodName,args);

    }

    }

    }

    调用自定义注解的方法,即进入相应切点,执行切点方法内容。

    三.    注意事项

    1.    自定义方法注解,不能放在Interface中,即注解接口方法不生效。

    如:

    public interface IUserService {

    /**

    * 查询用户列表

    * @return

    * @throws Exception

    */

    @SystemServiceLog(description = "用户列表") //此自定义注解不生效,不进入切点

    List queryUsers() throws Exception;

    }

    2.    自定义方法注解只能作用于直接调用的方法,继承父类的自定义注解不生效。

    如:

    public class UserServiceImpl extends BaseServiceImpl implements IUserService {

    @Override

    public List queryUsers() throws Exception {

    return query();

    }

    }

    public class BaseServiceImpl implements IBaseService{

    ...

    @Override

    @SystemServiceLog(description = "查询对象列表")

    public List query() {

    return nutzDao.query(entityClass, null);

    }

    }

    //因直接调用 UserServiceImpl 类中的queryUsers方法,故其父类中的 query自定义注解不生效。

    //正确的自定义注解方式

    public class UserServiceImpl extends BaseServiceImpl implements IUserService {

    @Override

    @SystemServiceLog(description = "查询对象列表")

    public List queryUsers() throws Exception {

    return query();

    }

    }

    展开全文
  • 通知类型4.1 @Before : 标注当前方法作为前置通知4.1.1 创建自定义注解(用于使用注解作为切入点)4.1.2 设置切面类以及Before切面方法4.1.3 @Before : 标注当前方法作为前置通知测试4.1.3.1 Controller层4.1.3.2 ...

    目录

    1.引入pom依赖

    • 主要是spring-boot-starter-aop依赖—>里面有需要的切面注解等配置
    
    
        <!--引入springboot父工程依赖-->
        <!--引入依赖作用:
        可以省去version标签来获得一些合理的默认配置
        -->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.2.RELEASE</version>
        </parent>
    
        <dependencies>
            <!--引入提供Web开发场景依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!--引入面向切面依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
    
        </dependencies>
    


    2.切入点表达式

    ——组成

    • 关键字(访问修饰符 返回值 包名.类名.方法名(参数)异常名)
    • 示例:execution(public String com.it.Controller.findById(int))
    组成部分解释
    关键字描述表达式的匹配模式(参看关键字列表)
    访问修饰符方法的访问控制权限修饰符
    类名方法所在的类(此处可以配置接口名称)
    异常方法定义中指定抛出的异常


    ——逻辑运算符

    运算符解释
    &&连接两个切入点表达式,表示两个切入点表达式同时成立的匹配
    ||连接两个切入点表达式,表示两个切入点表达式成立任意一个的匹配
    !连接单个切入点表达式,表示该切入点表达式不成立的匹配


    ——通配符

    *示例:execution(public * com.it.*.UserService.find*(*))
    *解释:匹配com.it包下的任意包中的UserService类或接口中所有find开头的带有一个参数的方法

    通配符解释
    *单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现

    • 实例: execution(public User com..UserService.findById(..))
    • 解释: 匹配com包下的任意包中的UserService类或接口中所有名称为findById并且返回是User实体的方法
    通配符解释
    ..多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写

    • 示例: execution(* *..*Service+.*(..))
    • 解释:匹配Service其子类方法
    通配符解释
    +专用于匹配子类类型


    ——范例

    • execution(* *(…))
    • execution(* (…))
    • execution(* .*(…))
    • execution(public * .*(…))
    • execution(public int .*(…))
    • execution(public void .*(…))
    • execution(public void com….(…))
    • execution(public void com…service..(…))
    • execution(public void com.it.service..(…))
    • execution(public void com.it.service.User*.*(…))
    • execution(public void com.it.service.Service.(…))
    • execution(public void com.it.service.UserService.*(…))
    • execution(public User com.it.service.UserService.find*(…))
    • execution(public User com.it.service.UserService.*Id(…))
    • execution(public User com.it.service.UserService.findById(…))
    • execution(public User com.it.service.UserService.findById(int))
    • execution(public User com.it.service.UserService.findById(int,int))
    • execution(public User com.it.service.UserService.findById(int,*))
    • execution(public User com.it.service.UserService.findById(*,int))
    • execution(public User com.it.service.UserService.findById())
    • execution(List com.it.service.*Service+.findAll(…))


    3. 启动类配置

    • 只需要注意下 其它的类都要在启动类同包或及下层目录即可 让@SpringBootApplication中@ComponentScan扫描到;
    • 如果类不在同级目录或下层目录 可以用@Import(Xxx.class)引入;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    /*
     * 面向切面编程Demo启动类
     * */
    @SpringBootApplication
    public class AOPTestApplication {
        public static void main(String[] args) {
            SpringApplication.run(AOPTestApplication.class, args);
        }
    }
    
    


    4.通知类型

    4.1 @Before : 标注当前方法作为前置通知

    • 前置通知:原始方法执行前执行,如果通知中抛出异常,阻止原始方法运行
    • 应       用:数据校验

    4.1.1 创建自定义注解(用于使用注解作为切入点)

    • 创建出名为BeforeDS 注解 作为后面的 before AOP切入点;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    
    /**
     * 自定义注解
     */
    @Retention(RetentionPolicy.RUNTIME)
    public @interface BeforeDS {
        public String value() default "Before_Value";
    }
    
    

    4.1.2 设置切面类以及Before切面方法

    • @Aspect: 设置当前类为切面类
    • @Before("@annotation(com.it.mhh.anno.BeforeDS)")
             @Before:标注当前方法作为前置通知
             @annotation:指定用注解进行切面
             com.it.mhh.anno.BeforeDS:注解的全路径名
    • JoinPoint: 主要是获取切入点方法相应数据
            getSignature()): 是获取到这样的信息 :修饰符+ 包名+组件名(类名) +方法名
            joinPoint.getArgs() :这里返回的是切入点方法的参数列表这里返回的是切入点方法的参数列表
            (MethodSignature) joinPoint.getSignature().getMethod().getAnnotation(BeforeDS.class) :获取切入点方法上的@BeforeDS注解
            …
    
    import com.it.mhh.anno.AfterDS;
    import com.it.mhh.anno.BeforeDS;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.*;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    import java.lang.reflect.Method;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * 通过业务代码动态切换数据源
     * 识别执行方法上得注解
     */
    @Component
    @Aspect //设置当前类为切面类
    //设置order=0,执行时机优先于AbstractRoutingDataSource.determineCurrentLookupKey
    @Order(0)
    public class SwitchDSAspect {
        
    
           /**
         * 标注当前方法作为前置通知
         */
        @Before("@annotation(com.it.mhh.anno.BeforeDS)")//用自定义注解 BeforeDS 作为切入点
        public void before(JoinPoint joinPoint) throws Throwable {
            Signature pointSignature = joinPoint.getSignature();
            System.err.println("切入点方法的修饰符+ 包名+组件名(类名) +方法名-->:"+pointSignature);
            
            Object[] args = joinPoint.getArgs();
            System.err.println("切入点方法的参数列表-->:"+ Arrays.toString(args));
            
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            BeforeDS beforeDS = method.getAnnotation(BeforeDS.class);
            String value = beforeDS.value();//获取切入点方法上BeforeDS注解的值
            System.err.println("切面类中before方法--自定义注解BeforeDS中的值为-->:" + value);
        }
    
    
    }
    


    4.1.3 @Before : 标注当前方法作为前置通知测试


    4.1.3.1 Controller层

    import com.it.mhh.anno.AfterDS;
    import com.it.mhh.service.AOPTestService;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("AOPtest")
    public class AOPTestController {
    
        @Value("#{AOPTestServiceImpl}")
        private AOPTestService aopTestService;
    
        @RequestMapping("before")
        public String beforeTest() {
            System.out.println("before测试-controller");
            return aopTestService.beforeTest();
        }
        
    }
    
    

    4.1.3.2 service层

    public interface AOPTestService {
        String beforeTest();
    }
    
    

    4.1.3.3 serviceimpl层

    import com.it.mhh.anno.BeforeDS;
    import com.it.mhh.service.AOPTestService;
    import org.springframework.stereotype.Service;
    
    @Service
    public class AOPTestServiceImpl implements AOPTestService {
    
    
        @BeforeDS //使用自定义注解 执行切面
        @Override
        public String beforeTest() {
            System.out.println("before测试-serviceimpl层");
            return "before测试end";
        }
        
    }
    
    


    @Before标注当前方法作为前置通知测试结果:

    • 首先可以看出先走了controller层并打印了日志,我在serviceimp层的方法上加入了自定义注解, 此注解作为切入点那么就会走设置的切入点方法,执行完切入点方法后执行后面代码;
    • 此方法没有入参 所以参数列表为空;
    • BeforeDS注解没有设置值,所以是默认值

    在这里插入图片描述
    在这里插入图片描述



    4.2 @After : 标注当前方法作为后置通知

    • 后置通知:原始方法执行后执行,无论原始方法中是否出现异常,都将执行通知
    • 应       用:现场清理

    4.2.1 创建自定义注解(用于使用注解作为切入点)

    • 创建出名为AfterDS 注解 作为后面的 after AOP切入点;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    /**
     * 自定义注解
     */
    @Retention(RetentionPolicy.RUNTIME)
    public @interface AfterDS {
        public String value() default "After_Value";
    }
    
    

    4.2.2 设置切面类以及After切面方法

    • @Aspect: 设置当前类为切面类
    • @After("@annotation(afterDS)")
             @After:标注当前方法作为后置通知
             @annotation:指定用注解进行切面
             afterDS:切面方法上的入参注解名
    • JoinPoint: 主要是获取切入点方法相应数据
            getSignature()): 是获取到这样的信息 :修饰符+ 包名+组件名(类名) +方法名
            joinPoint.getArgs() :这里返回的是切入点方法的参数列表这里返回的是切入点方法的参数列表
            …
    
    import com.it.mhh.anno.AfterDS;
    import com.it.mhh.anno.BeforeDS;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.*;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    import java.lang.reflect.Method;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * 通过业务代码动态切换数据源
     * 识别执行方法上得注解
     */
    @Component
    @Aspect //设置当前类为切面类
    //设置order=0,执行时机优先于AbstractRoutingDataSource.determineCurrentLookupKey
    @Order(0)
    public class SwitchDSAspect {
        
        /*
         * 标注当前方法作为后置通知
         * */
        @After("@annotation(afterDS)") //用自定义注解 AfterDS 作为切入点
        public void after(JoinPoint joinPoint, AfterDS afterDS) {
            Signature pointSignature = joinPoint.getSignature();
            System.err.println("切入点方法的修饰符+ 包名+组件名(类名) +方法名-->:" + pointSignature);
    
            Object[] args = joinPoint.getArgs();
            System.err.println("切入点方法的参数列表-->:" + Arrays.toString(args));
    
            String value = afterDS.value();
            System.err.println("切面类中after方法--自定义注解中的值为->" + value);
    
        }
    
    }
    


    4.2.3 @After : 标注当前方法作为后置通知测试


    4.2.3.1 Controller层

    import com.it.mhh.anno.AfterDS;
    import com.it.mhh.service.AOPTestService;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("AOPtest")
    public class AOPTestController {
    
        @Value("#{AOPTestServiceImpl}")
        private AOPTestService aopTestService;
    
        @AfterDS("afterController")
        @PostMapping("after/{name}")
        public String afterTest(@PathVariable("name") String name) {
            System.out.println("after测试-controller");
            return aopTestService.afterTest(name);
        }
        
    }
    
    

    4.2.3.2 service层

    public interface AOPTestService {
       String afterTest(String name);
    }
    
    

    4.2.3.3 serviceimpl层

    import com.it.mhh.anno.BeforeDS;
    import com.it.mhh.service.AOPTestService;
    import org.springframework.stereotype.Service;
    
    @Service
    public class AOPTestServiceImpl implements AOPTestService {
    
    
        @Override
        public String afterTest(String name) {
            System.out.println("after测试-serviceimpl层");
            return "afterTest测试end--入参姓名-->:"+name;
        }
        
    }
    
    


    @After : 标注当前方法作为后置通知 测试结果:

    • 首先可以看出在controller层的方法上加入了自定义注解@AfterDS(afterController),然后代码走了controller层并打印了日志,也走完了serviceimp层的方法以及打印了日志, 之后执行了切入点方法的代码;
    • 此方法有一个入参 所以参数列表中有一个值;
      @AlterDS()设置了value值 所以打印的就是设置的值

    在这里插入图片描述
    在这里插入图片描述



    4.3 @Around: 标注当前方法作为环绕通知

    • 环绕通知:在原始方法执行前后均有对应执行执行,还可以阻止原始方法的执行
    • 应       用:十分强大,可以做任何事情

    4.3.1 设置切面类以及@Around切面方法

    • @Aspect: 设置当前类为切面类
    • @Around(“pointCut()”)------>@Pointcut(value = “execution(public String com.it.mhh.service.impl.AOPTestServiceImpl.pointCutTest())”)
             @Around:标注当前方法作为环绕通知
             pointCut():自定义的方法,此方法上有一个注解 @Pointcut()
             @Pointcut():此注解的value值为切入点表达式
    • JoinPoint: 主要是获取切入点方法相应数据
            getSignature()): 是获取到这样的信息 :修饰符+ 包名+组件名(类名) +方法名
            joinPoint.getArgs() :这里返回的是切入点方法的参数列表这里返回的是切入点方法的参数列表
             ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotations():获取切入点方法上的所有注解
            …
    
    import com.it.mhh.anno.AfterDS;
    import com.it.mhh.anno.BeforeDS;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.*;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    import java.lang.reflect.Method;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * 通过业务代码动态切换数据源
     * 识别执行方法上得注解
     */
    @Component
    @Aspect //设置当前类为切面类
    //设置order=0,执行时机优先于AbstractRoutingDataSource.determineCurrentLookupKey
    @Order(0)
    public class SwitchDSAspect {
        
        //    @Pointcut(value = "@annotation(com.it.mhh.anno.DS)")
        @Pointcut(value = "execution(public String com.it.mhh.service.impl.AOPTestServiceImpl.pointCutTest())")
        public void pointCut() {
        }
      /*
         *标注当前方法作为环绕通知
         * */
        @Around("pointCut()")
        public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
            //获取执行签名信息
            Signature signature = joinPoint.getSignature();
            //通过签名获取执行类型(接口名)
            String targetClass = signature.getDeclaringTypeName();
            //通过签名获取执行操作名称(方法名)
            String targetMethod = signature.getName();
            //获取操作前系统时间beginTime
            long beginTime = System.currentTimeMillis();
            //消息入参joinPoint.getArgs() 及执行结束 反参ret 之后return到请求页面
            System.err.println("环绕通知在此方法之前执行的代码");
            Object ret = joinPoint.proceed(joinPoint.getArgs());
            System.err.println("环绕通知在此方法之后执行的代码");
            //获取操作后系统时间endTime
            long endTime = System.currentTimeMillis();
            System.err.println(targetClass + " 中 " + targetMethod + " 运行时长 " + (endTime - beginTime) + "ms");
    
    
            Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
            Annotation[] annotations = method.getAnnotations();
            System.err.println("此方法上的所以注解:"+ Arrays.toString(annotations));
    
    
            System.err.println("真实反参--》"+ret);
            //这里可以修改返回数据
            return ret+"--》:通过环绕通知修改的参数";
        }
    
    }
    


    4.3.2 @Around : 标注当前方法作为环绕通知测试


    4.3.2.1 Controller层

    import com.it.mhh.anno.AfterDS;
    import com.it.mhh.service.AOPTestService;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("AOPtest")
    public class AOPTestController {
    
        @Value("#{AOPTestServiceImpl}")
        private AOPTestService aopTestService;
    
        @PostMapping("pointCut")
        public String pointCutTest() {
            System.out.println("pointCutTest测试-controller");
            return aopTestService.pointCutTest();
        }
        
    }
    
    

    4.3.2.2 service层

    public interface AOPTestService {
       String pointCutTest();
    }
    
    

    4.3.2.3 serviceimpl层

    import com.it.mhh.anno.BeforeDS;
    import com.it.mhh.service.AOPTestService;
    import org.springframework.stereotype.Service;
    
    @Service
    public class AOPTestServiceImpl implements AOPTestService {
    
    
        @Override
        @Order
        public String pointCutTest() {
            System.out.println("pointCutTest测试-serviceimpl层");
            return "pointCutTest测试end";
        }
        
    }
    
    


    @Around : 标注当前方法作为环绕通知 测试结果:

    • @Around环绕通知可以修改返回参数
    • 切入点为AOPTestServiceImpl类pointCutTest()方法
      所以首先走了controller并打印日志 然后到了pointCutTest()方法 在此方法之前走了环绕通知方法的joinPoint.proceed(joinPoint.getArgs())代码之前的编码,然后接着走AOPTestServiceImpl类pointCutTest()方法里的代码,走完后会回到环绕通知的代码并执行完后返回结束;
    • method.getAnnotations():这里 好像发现获取方法上的注解 获取不到@Override

    在这里插入图片描述


    在这里插入图片描述



    4.4 @AfterReturning: 标注当前方法作为返回后通知

    • 返回后通知:原始方法正常执行完毕并返回结果后执行,如果原始方法中抛出异常,无法执行
    • 应       用:返回值相关数据处理

    4.4.1 设置切面类以及@AfterReturning切面方法

    • @Aspect: 设置当前类为切面类
    • @AfterReturning(value = “execution(public String com.it.mhh.service.impl.AOPTestServiceImpl.afterReturningTest(int ,int ))”, returning = “result”)
             @AfterReturning:标注当前方法作为返回后通知
             execution:切入点表达式—匹配执行指定方法
             returning:设定使用通知方法参数接收返回值的变量名
    • JoinPoint: 主要是获取切入点方法相应数据
            getSignature()): 是获取到这样的信息 :修饰符+ 包名+组件名(类名) +方法名
            joinPoint.getArgs() :这里返回的是切入点方法的参数列表这里返回的是切入点方法的参数列表
             ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotations():获取切入点方法上的所有注解
            …
    
    import com.it.mhh.anno.AfterDS;
    import com.it.mhh.anno.BeforeDS;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.*;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    import java.lang.reflect.Method;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * 通过业务代码动态切换数据源
     * 识别执行方法上得注解
     */
    @Component
    @Aspect //设置当前类为切面类
    //设置order=0,执行时机优先于AbstractRoutingDataSource.determineCurrentLookupKey
    @Order(0)
    public class SwitchDSAspect {
        
          /*
         *  标注当前方法作为返回后通知
         *
         * 当连接点方法成功执行后,返回通知方法才会执行,如果连接点方法出现异常,则返回通知方法不执行。
         * 返回通知方法在目标方法执行成功后才会执行,所以,返回通知方法可以拿到目标方法(连接点方法)执行后的结果。
         * */
        //returning :设定使用通知方法参数接收返回值的变量名
        @AfterReturning(value = "execution(public String com.it.mhh.service.impl.AOPTestServiceImpl.afterReturningTest(int ,int ))", returning = "result")
        public void afterReturning(JoinPoint joinPoint, Object result) {
            Signature pointSignature = joinPoint.getSignature();
            System.err.println("切入点方法的修饰符+ 包名+组件名(类名) +方法名-->:" + pointSignature);
    
            Object[] args = joinPoint.getArgs();
            System.err.println("切入点方法的参数列表-->:" + Arrays.toString(args));
    
            System.err.println("切入点返回参-->:"+result);
        }
    }
    


    4.4.2 @AfterReturning: 标注当前方法作为返回后通知测试


    4.4.2.1 Controller层

    import com.it.mhh.anno.AfterDS;
    import com.it.mhh.service.AOPTestService;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("AOPtest")
    public class AOPTestController {
    
        @Value("#{AOPTestServiceImpl}")
        private AOPTestService aopTestService;
    
        @PostMapping("afterReturning/{i1}/{i2}")
        public String afterReturningTest(@PathVariable("i1") int i1, @PathVariable("i2") int i2) {
            System.out.println("afterReturningTest测试-controller");
            return aopTestService.afterReturningTest(i1, i2);
        }
        
    }
    
    

    4.4.2.2 service层

    public interface AOPTestService {
           String afterReturningTest(int i1, int i2);
    }
    
    

    4.4.2.3 serviceimpl层

    import com.it.mhh.anno.BeforeDS;
    import com.it.mhh.service.AOPTestService;
    import org.springframework.stereotype.Service;
    
    @Service
    public class AOPTestServiceImpl implements AOPTestService {
    
    
        @Override
        public String afterReturningTest(int i1, int i2) {
            System.out.println("afterReturningTest测试-serviceimpl层");
            return "afterReturningTest测试end--->int总和:" + (i1 + i2);
        }
        
    }
    
    


    @AfterReturning : 标注当前方法作为返回后通知 测试结果:

    • 原始方法正常执行完毕并返回结果后执行,如果原始方法中抛出异常,无法执行
    • 切入点为AOPTestServiceImpl类afterReturningTest(int ,int )方法

    在这里插入图片描述


    在这里插入图片描述



    4.5 @AfterThrowing: 标注当前方法作为抛出异常后通知

    • 抛出异常后通知:原始方法抛出异常后执行,如果原始方法没有抛出异常,无法执行
    • 应       用:对原始方法中出现的异常信息进行处理

    4.5.1 设置切面类以及@AfterThrowing切面方法

    • @Aspect: 设置当前类为切面类
    • @AfterThrowing(value = “execution(public String com.it.mhh.service.impl.AOPTestServiceImpl.afterThrowingTest(String))”, throwing = “e”)
             @AfterThrowing:标注当前方法作为抛出异常后通知
             execution:切入点表达式—匹配执行指定方法
             throwing:设定使用通知方法参数接收原始方法中抛出的异常对象名
    • JoinPoint: 主要是获取切入点方法相应数据
            getSignature()): 是获取到这样的信息 :修饰符+ 包名+组件名(类名) +方法名
            joinPoint.getArgs() :这里返回的是切入点方法的参数列表这里返回的是切入点方法的参数列表
             ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotations():获取切入点方法上的所有注解
            …
    
    import com.it.mhh.anno.AfterDS;
    import com.it.mhh.anno.BeforeDS;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.*;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    import java.lang.reflect.Method;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * 通过业务代码动态切换数据源
     * 识别执行方法上得注解
     */
    @Component
    @Aspect //设置当前类为切面类
    //设置order=0,执行时机优先于AbstractRoutingDataSource.determineCurrentLookupKey
    @Order(0)
    public class SwitchDSAspect {
        
        /*
         * 标注当前方法作为异常后通知
         * 异常通知方法只在连接点方法出现异常后才会执行,否则不执行。
         * 在异常通知方法中可以获取连接点方法出现的异常。在切面类中异常通知方法
         * */
        //throwing :设定使用通知方法参数接收原始方法中抛出的异常对象名
        @AfterThrowing(value = "execution(public String com.it.mhh.service.impl.AOPTestServiceImpl.afterThrowingTest(String))", throwing = "e")
        public void afterThrowing(JoinPoint joinPoint, Exception e) {
            Signature pointSignature = joinPoint.getSignature();
            System.err.println("切入点方法的修饰符+ 包名+组件名(类名) +方法名-->:" + pointSignature);
    
            Object[] args = joinPoint.getArgs();
            System.err.println("切入点方法的参数列表-->:" + Arrays.toString(args));
    
            System.err.println("切入点异常-->:" + e);
        }
    }
    


    4.5.2 @AfterThrowing: 标注当前方法作为异常后通知测试


    4.5.2.1 Controller层

    import com.it.mhh.anno.AfterDS;
    import com.it.mhh.service.AOPTestService;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("AOPtest")
    public class AOPTestController {
    
        @Value("#{AOPTestServiceImpl}")
        private AOPTestService aopTestService;
    
        @PostMapping("afterThrowing/{string}")
        public String afterThrowingTest(@PathVariable("string") String string) {
            System.out.println("afterThrowingTest测试-controller");
            return aopTestService.afterThrowingTest(string);
        }
        
    }
    
    

    4.5.2.2 service层

    public interface AOPTestService {
           String afterThrowingTest(String string);
    }
    
    

    4.5.2.3 serviceimpl层

    import com.it.mhh.anno.BeforeDS;
    import com.it.mhh.service.AOPTestService;
    import org.springframework.stereotype.Service;
    
    @Service
    public class AOPTestServiceImpl implements AOPTestService {
    
    
        @Override
        public String afterThrowingTest(String string) {
            System.out.println("afterThrowingTest测试-serviceimpl层");
            int i = 1 / 0;
            return "afterThrowingTest测试end--->String值:" + string;
        }
        
    }
    
    


    @AfterThrowing: 标注当前方法作为异常后通知 测试结果:

    • 抛出异常后通知:原始方法抛出异常后执行,如果原始方法没有抛出异常,无法执行
    • 切入点为AOPTestServiceImpl类afterThrowingTest(String)方法

    在这里插入图片描述


    在这里插入图片描述









    链接:SpringBoot之AOP面向切面编程实例 源代码下载地址

    展开全文
  • java中Aop面向切面编程实例,权限校验AppKeyValidation及数据解密及ResourceBundle加载文件。使用场景:不同系统间当登录或者请求相关接口时校验是否含有AppKey等信息。如果有的话,可以处理相关的业务逻辑,如果...

    java中Aop面向切面编程实例,权限校验AppKeyValidation及数据解密及ResourceBundle加载文件。

    使用场景:不同系统间当登录或者请求相关接口时校验是否含有AppKey等信息。如果有的话,可以处理相关的业务逻辑,如果没有的话,则返回相应的返回信息,前后端接口相关信息约定好,相关数据可以进行加密。

    对相关的接口添加自定义注解,Aop进行方法的增加,对相关自定义注解进行校验。

    1.自定义注解设置

    package com.yl.oms.api.base.annotations.appkey;

    import java.lang.annotation.Documented;

    import java.lang.annotation.ElementType;

    import java.lang.annotation.Retention;

    import java.lang.annotation.RetentionPolicy;

    import java.lang.annotation.Target;

    import org.springframework.web.bind.annotation.Mapping;

    /**

    * 抽象验证AppKey接口规范

    * @author Tolk

    */

    @Target({ElementType.METHOD, ElementType.TYPE})

    @Retention(RetentionPolicy.RUNTIME)

    @Documented

    @Mapping

    public @interface AppKeyValidation {

    }

    2.接口添加@AppKeyValidation注解,对接口进行方法的增强

    /**

    * CRM传递项目信息同步至EHR

    * @return result

    */

    @AppKeyValidation

    @ResponseBody

    @RequestMapping(value = "/synProjectFromCRM")

    public ResultMessage synProjectFromCRM(@RequestBody String jsonParam,HttpServletRequest request,String appKey){

    logger.info("[synProjectFromCRM]:CRM传递项目信息同步至EHR;time=" + DateConvertUtils.getTime());

    logger.info("[synProjectFromCRM]:param:" + jsonParam);

    return apiCrmService.synProjectFromCRM(jsonParam);

    }

    3.配置文件的添加 config.properties

    #接口appKey验证 一下的若包含则不做 key+param hash比较,多个逗号分隔;

    appkeys = CRM-EHR,TEST-KEY

    4.具体的切面类的编写,校验添加了自定义注解接口相关信息

    校验主要是对接口方法中的参数,类型进行校验。对数据进行解密处理,然后调用执行相关接口处理相关业务逻辑。

    package com.yl.oms.api.base.annotations.appkey;

    import com.yl.entity.vo.base.ResultMessage;

    import com.yl.facade.api.ApiReceiveQueueService;

    import com.yl.oms.api.util.DESUtil;

    import com.yl.util.lang.StringUtils;

    import net.sf.json.JSONObject;

    import org.aspectj.lang.ProceedingJoinPoint;

    import org.aspectj.lang.annotation.Around;

    import org.aspectj.lang.annotation.Aspect;

    import org.aspectj.lang.reflect.MethodSignature;

    import org.slf4j.Logger;

    import org.slf4j.LoggerFactory;

    import org.springframework.beans.factory.annotation.Autowired;

    import org.springframework.core.annotation.Order;

    import org.springframework.stereotype.Component;

    import javax.servlet.http.HttpServletRequest;

    import java.lang.reflect.Method;

    import java.util.ResourceBundle;

    /**

    * APPKey验证类AOP执行调度

    * @author Tolk

    */

    @Aspect

    @Component

    @Order(100)

    public class AppKeyValidationAspect {

    private static Logger logger = LoggerFactory.getLogger(AppKeyValidationAspect.class);

    @Autowired

    ApiReceiveQueueService apiReceiveQueueService;

    /**

    * Around

    * 手动控制调用核心业务逻辑,以及调用前和调用后的处理,

    * 注意:当核心业务抛异常后,立即退出,转向AfterAdvice

    * 执行完AfterAdvice,再转到ThrowingAdvice

    * @param pjp

    * @return

    * @throws Throwable

    */

    @Around("@annotation(com.yl.oms.api.base.annotations.appkey.AppKeyValidation)")

    // @Pointcut("execution(public * com.yl.oms.api.controller.cti.AddCtiCallRecordController*add(..)) && @annotation(com.yl.oms.api.base.annotations.appkey.AppKeyValidation)")

    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {

    Object retVal = null;

    // String resultStr = null;

    MethodSignature ms=(MethodSignature) pjp.getSignature();

    Method method=ms.getMethod();

    // AppKeyValidation appKeyValidation = method.getAnnotation(AppKeyValidation.class);

    //获取方法Code

    String methodName = method.getName();

    ResultMessage sApiValidationResult = null;

    String appKey = null;

    String appApiHash = null;

    String needEncrypt = null;

    String sOldParam = null;

    String sNewParam = null;

    String secretKeyStr = null;

    try{

    //参数验证

    if(pjp.getArgs().length != 3){

    sApiValidationResult = new ResultMessage("接口参数异常, 非约定规范(指定的三个参数)! ");

    }else{

    HttpServletRequest request = (HttpServletRequest) pjp.getArgs()[1];

    appKey = request.getHeader("Dapi-App-Key");

    appApiHash = request.getHeader("Dapi-Hash");

    needEncrypt = request.getHeader("Dapi-Encrypt");

    sOldParam = (String) pjp.getArgs()[0];

    secretKeyStr = appKey;

    if(appKey != null && appKey.length() < 32){

    secretKeyStr = DESUtil.string2MD5(appKey);

    }

    if(appKey == null || "".equals(appKey)){

    sApiValidationResult = new ResultMessage("AppKey参数验证失败! ");

    }else if(appApiHash == null || "".equals(appApiHash)){

    sApiValidationResult = new ResultMessage("AppApiHash参数验证失败! ");

    }else{

    //验证ApiHash合法性

    String sApiHash = DESUtil.string2MD5(appKey + sOldParam);

    boolean isCheckPass = (sApiHash != null && appApiHash.equals(sApiHash));

    //获取config.properties中的配置信息

    ResourceBundle.clearCache();

    ResourceBundle bundle = ResourceBundle.getBundle("config");

    String unCheckAppkeys = StringUtils.safeToString(bundle.getString("appkeys"),"CRM-EHR");

    //CRM接口不做hash验证 只验证 appKey = CRM-EHR

    if(unCheckAppkeys.contains(appKey)){

    isCheckPass = true;

    }

    if(isCheckPass){

    try{

    if(needEncrypt != null && "true".equals(needEncrypt)){

    sNewParam = DESUtil.decrypt(sOldParam, secretKeyStr);

    }else{

    sNewParam = sOldParam;

    }

    pjp.getArgs()[0] = sNewParam;

    pjp.getArgs()[2] = appKey;

    try{

    //调用执行原代码

    retVal = pjp.proceed(pjp.getArgs());

    if(retVal == null){

    sApiValidationResult = new ResultMessage(true, "成功");

    }else if(method.getReturnType() == String.class){

    sApiValidationResult = new ResultMessage(true, retVal.toString());

    }else if(method.getReturnType() == ResultMessage.class){

    sApiValidationResult = (ResultMessage)retVal;

    }

    }catch(Exception e){

    sApiValidationResult = new ResultMessage("执行API处理失败!Message: " +e.toString());

    }

    }catch(Exception e){

    sApiValidationResult = new ResultMessage("参数内容解密失败!");

    }

    }else{

    sApiValidationResult = new ResultMessage("AppKey和 参数内容 合法性 验证失败!");

    }

    }

    }

    }catch(Exception e){

    sApiValidationResult = new ResultMessage("程序异常, 请联系接口研发人员, ErrorMessage: " + e.toString());

    logger.error("API方法异常("+methodName+"), 程序执行异常, Message: " + e.toString() );

    }

    if(sApiValidationResult == null){

    sApiValidationResult = new ResultMessage("返回值异常,请联系研发人员!");

    }

    //当失败的时候打印参数

    if(sApiValidationResult != null && !sApiValidationResult.isSuccess()){

    logger.info("invokeError-" + methodName + ", appKey: " + appKey + ", appApiHash: " + appApiHash

    + ", Result: "+ sApiValidationResult+", Param: " + (sNewParam == null ? sOldParam : sNewParam));

    }

    if(sApiValidationResult != null && secretKeyStr != null && "true".equals(needEncrypt)){

    if(method.getReturnType() == String.class){

    return DESUtil.encrypt(sApiValidationResult.toString(), secretKeyStr);

    }

    }

    if(method.getReturnType() == String.class){

    retVal = sApiValidationResult.toString();

    }else if(method.getReturnType() == ResultMessage.class){

    retVal = sApiValidationResult;

    }else if(method.getReturnType() == JSONObject.class){

    retVal = JSONObject.fromObject(sApiValidationResult);

    }else if(method.getReturnType() == void.class){

    retVal = null;

    }

    return retVal;

    }

    }

    总结:主要是通过自定义注解的使用,AOP面向切面编程思想具体使用,对添加了自定义注解的接口方法的增强。然后处理相关的业务逻辑,这里主要是权限校验,数据解密业务场景的使用。

    展开全文
  • 1. pom 引入aop jarorg.springframework.bootspring-boot... 定义切面 Aspect@Aspect@Component // 这句不能少public class TestAspect {private Logger logger = Logger.getLogger(getClass());@Pointcut("executio...

    1. pom 引入aop jar

    org.springframework.boot

    spring-boot-starter-aop

    2. 定义切面 Aspect

    @Aspect

    @Component // 这句不能少

    public class TestAspect {

    private Logger logger = Logger.getLogger(getClass());

    @Pointcut("execution(* com.test.server1.controller.ComputerController.test(..))")

    public void testPoint() {}

    @Before(value="testPoint()")

    public void handleBeforeMethod()

    {

    logger.info("handleBeforeMethod before");

    }

    @Around(value = "testPoint()")

    public String handleAroundMethod(ProceedingJoinPoint joinPoint) throws Throwable

    {

    logger.info("handleAroundMethod Around");

    return (String) joinPoint.proceed();

    }

    @After(value = "testPoint()")

    public void handleAfterMethod()

    {

    logger.info("handleAfterMethod After");

    }

    }

    展开全文
  • 参考博客: 大神的博客,点赞请去大神贴,本人仅做参考。 SpringBoot中的AOP处理1 理解AOP1.1 什么是AOP1.2 AOP体系与概念2 AOP实例2.1 第一个实例2.2 第...AOP(Aspect Oriented Programming),面向切面思想,是Sprin
  • 一直心心念的想写一篇关于AOP切面实例的博文,拖更了许久之后,今天终于着手下笔将...面向切面编程则是指,对于一个我们已经封装好的类,我们可以在编译期间或在运行期间,对其进行切割,把立方体切开,在原有的方法里
  • @TOCJAVA面向切面编程(AOP)实例 定义切面注解 @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface KpiAspectAnnotation { String desc() default "...
  • 开发者(KaiFaX)面向全栈工程师的开发者专注于前端、Java/Python/Go/PHP的技术社区作者 |Amos来源 | https://amos-x.com/index.php/...
  • AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的一种技术。 AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式...
  • 1.aop全称Aspect Oriented Programming 面向切面编程2.aop应用场景场景一: 记录日志场景二: 监控方法运行时间 (监控性能)场景三: 权限控制场景四: 缓存优化 (第一次调用查询数据库,将查询结果放入内存对象, 第...
  • AOP面向切面编程

    2021-07-31 09:47:38
    1、 面向切面编程AOP 作用:在不改变程序代码的基础上进行功能增强。 原理:Proxy代理。即假如业务是从淘宝网买书,那么淘宝网只需要把数放在包裹并填写地址,剩下的任务由快递公司完成,在这个过程中,快递公司...
  • 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码...
  • AOP(Aspect Orient Programming),也就是 面向切面编程,AOP 是一种编程思想,是OOP(面向对象编程)的一种补充,面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面。 为什么需要AOP ...
  • 前面两篇文章记录了 Spring IOC 的相关知识,本文记录 Spring 中的另一特性 AOP 相关知识。...AOP (Aspect Orient Programming),直译过来就是 面向切面编程。AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。
  • 1.切面类的实现 切面类都是通过实现各种特定的接口来实现的,缺点是必须要实现特定的接口,且一个类基本上只有一个重写方法是有用的。 对于普通的类,若不实现特定的接口,可以通过可以通过注解转化为切面类(通知类...
  • 一、Spring AOP(面向切面编程)是什么? 二、Spring JDK动态代理 1. 创建项目 2. 创建接口 StudentDao 3. 创建实现类 StudentDaoImpl 4. 创建切面类 MyAspect 5. 创建代理类 MyBeanFactory 6. 创建...
  • 结合 Redux应用实例与 applyMiddleware源码,对 Redux中间件的实现原理进行分析。在此基础上,对“面向切面”这一经典的编程思想建立初步的认识。
  • PHP面向切面编程组件

    2021-03-25 10:23:24
    面向切面编程的思路,是解决不断变化的业务逻辑与写出便于维护代码的解决方法之一。下面是向切面式组件源码,是根据AOP的思路设计的。spl_autoload_register(array('ExtensionFactory', 'autoload'))...
  • } } 测试结果: 注解方式类型的顺序: 环绕前通知 前置通知 (运行方法) 异常通知 最终通知 后置通知 环绕后通知 xml配置方式: 所以我们只需要把aop:aspectj-autoproxy注释掉,切面类的注释方式就失效了。...
  • 想象一段自顶而下的程序,在这一段程序中的某个方法想要在执行后打印出日志,这时候使用面向切面编程的思想就可以很好的解决这个问题,我们可以通过代理模式来实现我们的打印日志功能,因为代理模式就是面向切面...
  • AOP(Aspect Oriented Programming)面向切面编程,是Spring框架中的内容,它是针对于一个事件的某个步骤或阶段,主要应用于:日志,事务处理,异常处理等方面,它的原理是:通过过滤,对指定的一些操作直接添加设定好...
  • 设计模式;面向切面编程;AOP;python
  • 一、eclipse新建java项目取名SpringTest二、导入sping包到构建路径还需要aspectjweaver.jar三、创建java类(当然先要创建各种包)IHelloService.javapackagecom.zjptcc.wxw.spring.hello;publicinterfaceIHelloService...
  • Spring容器中的javabean对象默认是立即加载(立即实例化:spring加载完成,立即创建对象) scope:属性 singleton:默认值为单例,默认也是立即加载,在加载完成spring容器的时候,bean对象已经创建完成 ...
  • 下面是向切面式组件源码,是根据AOP的思路设计的:if (function_exists('__autoload')) {trigger_error("Extension: It looks like your code is using an __autoload() function. Extension uses spl_autoload_...
  • Spring中面向切面编程

    2021-02-16 17:43:22
    Spring AOP——Spring 中面向切面编程 前面两篇文章记录了 Spring IOC 的相关知识,本文记录 Spring 中的另一特性 AOP 相关知识。 部分参考资料: 《Spring实战(第4版)》 《轻量级 JavaEE 企业应用实战(第四版...
  • 其实在做AOP切面编程时,最常使用也必备的一个标签就是,< aop:aspectj-autoproxy></aop:aspectj-autoproxy>, 我们在容器中需要添加这个元素,当Spring IOC容器侦测到bean配置文件中的< aop:aspectj...
  • 这里写自定义目录标题1. AOP实例1.1 第一个实例1.2第二个实例2.AOP相关注解2.1 @Pointcut2.2 @...有需要可以看上一篇文章自学很好的例子Spring AOP——Spring 中面向切面编程(一) 1. AOP实例 使用 AOP,首先需要引入
  • 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 42,714
精华内容 17,085
关键字:

面向切面编程实例