AOP理解

https://blog.csdn.net/qq_26525215/article/details/52400791

使用场景:

  日志、鉴权等一些和业务无关且重复的功能

几个基本概念:

  切点:需要增加功能的位置(可以通过注解或者pointCut方法)

  切面:需要增加的功能的代码(通过定义一个xxAcept类,选择性的添加方法,为切点在不同位置【代码段的前中后】增加功能)

  织入:Spring和其它纯Java AOP框架一样,在运行时完成织入

  通知:通知有各种类型,其中包括“around”、“before”和“after”等通知

动态代理实现AOP(JDKProxy):

   通过动态代理的方式实现AOP,动态代理生成的这个对象,在具体的方法上,新增了切面中定义的功能,使得我们在不改变原对象的基础上新增了我们需要的功能。

   代理会生成一个类,这个类继承这个接口,并且代理要切面的类,在实现具体的方法时,实际上是调用了原来类的方法,只是在调用前和调用后做了一些事情而已。 

  这种方式只能为接口创建代理实例,而对于没有通过接口定义业务方法的类,可以通过CGLib创建动态代理。

  

 

AOP失效的情景,为什么会失效?

https://blog.csdn.net/u012373815/article/details/77345655

1.在对象内部的方法中调用该对象的其他使用aop机制的方法,被调用方法的aop注解失效。

原因:

  正常aop的顺序是这样的:一个类作为被代理对象,动态的生成一个代理对象,在这个新的代理对象中的invoke()方法里会执行一些额外新增的功能和被代理对象的某个方法,而这个方法是通过调用被代理对象的这个方法而实现的。当使用注解增加一个aop切点时,实际上是把这个类作为了一个被代理对象,因此在执行一个被调用的方法时,这个aop会失效。

2.private方法不生效

   private方法一定是这个类的某个方法去调用的,本质和上一种情况是一样的,因此aop失效。

 

初识aop的一个demo:

MyAspect.java

package com.test.aoptest.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Arrays;

/**
 * @author gaoyuan 
 * @date 2019/7/15 11:27
 */
@Aspect
@Component
public class MyAspect {

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

    @Pointcut("execution(public * com.test.aoptest.service.*.*(..))")
    public void pointCut(){

    }

    @Before("pointCut()")
    public void before(JoinPoint joinPoint) throws Throwable {
        // 接收到请求,记录请求内容
        logger.info("【注解:Before】------------------切面  before");
        ServletRequestAttributes attributes = (ServletRequestAttributes)
                RequestContextHolder.getRequestAttributes();
        // 记录下请求内容
        logger.info("【注解:Before】执行的业务方法名=CLASS_METHOD : " +
                joinPoint.getSignature().getDeclaringTypeName() + "." +
                joinPoint.getSignature().getName());
        logger.info("【注解:Before】业务方法获得的参数=ARGS : " + Arrays.toString(joinPoint.getArgs()));
    }

    @AfterReturning(returning = "ret", pointcut = "pointCut()")
    public void afterReturning(Object ret) throws Throwable {
        // 处理完请求,返回内容
        logger.info("【注解:AfterReturning】这个会在切面最后的最后打印,方法的返回值 : " + ret);
    }

    @AfterThrowing("pointCut()")
    public void afterThrowing(JoinPoint jp){
        logger.info("【注解:AfterThrowing】方法异常时执行.....");
    }

    @After("pointCut()")
    public void after(JoinPoint jp){
        logger.info("【注解:After】方法最后执行.....");
    }

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint pjp) {
        logger.info("【注解:Around . 环绕前】方法环绕start.....");
        try {
            //如果不执行这句,会不执行切面的Before方法及controller的业务方法
            Object o =  pjp.proceed();
            logger.info("【注解:Around. 环绕后】方法环绕proceed,结果是 :" + o);
            return o;
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
    }
}

AopConfiguration.java

package com.test.aoptest.configuration;


import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * @author gaoyuan 
 * @date 2019/7/15 11:39
 */
@Configuration
@ComponentScan("com.test.aoptest.aspect")
@EnableAspectJAutoProxy
public class AopConfiguration {
}

HelloController.java

package com.test.aoptest.controller;

import com.test.aoptest.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author gaoyuan (yuangao@rd.netease.com)
 * @date 2019/7/15 11:43
 */
@RestController
@RequestMapping("/")
public class HelloController {

    @Autowired
    private HelloService helloService;

    @RequestMapping("hello")
    public String hello() {
        return helloService.sayHello();
    }

}

HelloService.java

package com.test.aoptest.service;

/**
 * @author gaoyuan
 * @date 2019/7/15 11:23
 */
public interface HelloService {
    String sayHello();

    void printHello();

    int addUser(String name, String pass);

}

 

HelloServiceImpl.java

package com.test.aoptest.service.impl;

import com.test.aoptest.service.HelloService;
import org.springframework.stereotype.Service;

/**
 * @author gaoyuan 
 * @date 2019/7/15 11:23
 */
@Service
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello() {
        return "hello";
    }

    @Override
    public void printHello() {
        System.out.println("hello");
    }

    @Override
    public int addUser(String name , String pass)
    {
        System.out.println("执行Hello组件的addUser添加用户:" + name);
        if(name.length() < 3 || name.length() > 10)
        {
            throw new IllegalArgumentException("name参数的长度必须大于3,小于10!");
        }
        return 20;
    }
}

AoptestApplication.java

package com.test.aoptest;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy(proxyTargetClass = true)
@EnableConfigurationProperties
public class AoptestApplication {

    public static void main(String[] args) {
        SpringApplication.run(AoptestApplication.class, args);
    }

}

application.properties

server.port=8080
spring.profiles.active=dev

application-dev.properties

这个文件其实撒都没有,做作了一下 啊哈哈哈

posted @ 2019-07-17 18:16  高圈圈  阅读(558)  评论(0编辑  收藏  举报