SpringBoot使用AOP(動態代理)


SpringBoot使用AOP(動態代理)

  • cgllib 需要添加依賴
<!--cglib動態代理-->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.12</version>
</dependency>
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
      <version>2.1.7.RELEASE</version>
  </dependency>

 

 

  1. 目標target(需要被增強的接口)
//目標target
public interface UserService {
    void login(String username, String password);
    void regist();
    void search();
    void update();
}

 

 

 

  1. 接口實現
/**
 * @Description
 * @Author zhoumm
 * @Version V1.0.0
 * @Since 1.0
 * @Date 2019-08-24
 */
@Service
public class UserServiceImpl implements UserService{
    @Override
    public void login(String username, String password) {
        System.out.println ("登錄");
    }

    @Override
    public void regist() {
        System.out.println ("注冊");
    }

    @Override
    public void search() {
        System.out.println ("userService search...");
    }

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

 

  1. 代理增強類
/**
 * @Description  代理增強類
 * @Author 
 * @Version V1.0.0
 * @Since 1.0
 * @Date 2019-08-25
 */
@Component
@Aspect  //標識為一個切面供容器讀取
public class UserServiceHelper {
    @Before("execution(* com.mmz.tkp.controller.aoptest.UserService.s*(..))")
    public void before(){
        System.out.println ("前置通知。。。");
    }

    @AfterReturning(value="execution(* com.mmz.tkp.controller.aoptest.UserService.s*(..))")
    public void afterReturning(){
        System.out.println ("后置通知。。。");
    }

    @Around("execution(* com.mmz.tkp.controller.aoptest.UserService.s*(..))")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println ("環繞前。。。");
        Object value = pjp.proceed();
        System.out.println (value);
        System.out.println ("環繞后。。。");
    }

    @After("execution(* com.mmz.tkp.controller.aoptest.UserService.s*(..))")
    public void after(){
        System.out.println ("最終通知。。。");
    }

    @AfterThrowing(value="execution(* *.s*(..))",throwing="ex")
    public void afterThrowing(JoinPoint jp,Throwable ex){
        System.out.println ("異常拋出通知" + ex);
    }

    @Pointcut("execution(* com.mmz.tkp.controller.aoptest.UserService.search(..))")
    public void mypointcut(){}

    @Pointcut("execution(* com.mmz.tkp.controller.aoptest.UserService.update(..))")
    public void mypointcut1(){}

    //使用@Pointcut來聲明切點,避免在每個通知中定義切點
    @Before("mypointcut()||mypointcut1()")
    public void before1(){
        System.out.println ("前置通知。。。。");
    }
}

 

 

  1. JDK動態代理工廠類
/**
 * @Description JDK動態代理工廠類
 * 在運行期 ,在JVM內部動態生成class字節碼對象(Class對象)
 * Jdk動態代理只針對於接口操作
 * @Author 
 * @Version V1.0.0
 * @Since 1.0
 * @Date 2019-08-24
 */
public class JDKProxyFactory implements InvocationHandler {
    //目標對象
    private Object target;

    public JDKProxyFactory(Object target) {
        this.target = target;
    }

    //使用Proxy創建代理對象
    public Object createProxy(){
        //目標類的類加載器對象
        ClassLoader classLoader = target.getClass().getClassLoader();
        //目標類的實現接口的Class[]
        Class<?>[] interfaces = target.getClass().getInterfaces();
        //當前對象需實現InvocationHandler接口
        return Proxy.newProxyInstance(classLoader,interfaces,this);
    }

    /**
     *
     * @param proxy  代理對象,一般不用
     * @param method 方法對象
     * @param args  方法參數
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //在調用目標對象方法前,統一做一些其他操作,即功能增強
        System.out.println ("例如:日志操作......");
        return method.invoke(target,args);
    }
}

 

  1. CGLIB動態代理
/**
 * @Description  CGLIB動態代理
 * CGLIB(Code Generation Library)是一個開源項目
 * 是一個強大的,高性能,高質量的Code生成類庫,它可以在運行期擴展Java類與實現Java接口。
 * CGLIB包的底層是通過使用一個小而快的字節碼處理框架ASM,來轉換字節碼並生成新的類
 *
 * 可以為沒有實現接口的類去做代理,也可以為實現接口的類去做代理。
 *
 * spring采用的是哪一種動態機制:
 *     如果目標對象,有接口,優先使用jdk動態代理
 *     如果目標對象,無接口,使用cglib動態代理。
 * @Author zhoumm
 * @Version V1.0.0
 * @Since 1.0
 * @Date 2019-08-24
 */
public class CglibProxyFactory implements MethodInterceptor {
    //目標對象
    private Object target;

    public CglibProxyFactory(Object target) {
        this.target = target;
    }

    //創建代理對象
    public Object createProxy(){
        //1.創建Enhancer
        Enhancer enhancer = new Enhancer();
        //2.傳遞目標對象Class
        enhancer.setSuperclass(target.getClass());
        //3.設置回調操作(相當於InvocationHandler)
        enhancer.setCallback(this);

        return enhancer.create();
    }


    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        //在調用目標對象方法前,統一做一些其他操作,即功能增強
        System.out.println ("例如:日志操作......");
        return method.invoke(target,args);
    }
}

 

  1. controller 代理測試
@Api(value = "aop", description = "面向切面編程")
@RestController
@RequestMapping("/kpt/aop")
@Slf4j
@Validated
public class AopBackGroundController {

    @Autowired
    private UserService userService;

    @ApiOperation(value = "JDK動態代理測試", httpMethod = "GET")
    @RequestMapping(value = "/jdkproxy", method = RequestMethod.GET)
    public void testJDKProxy(){
        //JDK動態代理
        userService.login("zz","123456");
        System.out.println ("--------------JDK動態代理------------");
        JDKProxyFactory jdkProxyFactory = new JDKProxyFactory(userService);
        UserService userServiceProxy = (UserService)jdkProxyFactory.createProxy();
        userServiceProxy.login("zz","123456");
    }

    @ApiOperation(value = "CGLIB動態代理測試", httpMethod = "GET")
    @RequestMapping(value = "/cglibproxy", method = RequestMethod.GET)
    public void testCGLIBProxy(){
        //CGLIB動態代理
        userService.regist();
        System.out.println ("--------------CGLIB動態代理------------");
        CglibProxyFactory cglibProxyFactory = new CglibProxyFactory(userService);
        UserService userServiceProxy = (UserService)cglibProxyFactory.createProxy();
        userServiceProxy.regist();
    }

    @ApiOperation(value = "AspectJ代理測試", httpMethod = "GET")
    @RequestMapping(value = "/aspectJproxy", method = RequestMethod.GET)
    public void testAspectJ(){
        //com.mmz.tkp.controller.aoptest.UserServiceHelper
        userService.search();
    }

    @ApiOperation(value = "切點通知測試", httpMethod = "GET")
    @RequestMapping(value = "/aspectJproxy", method = RequestMethod.GET)
    public void testPointcutAdvice(){
        //com.mmz.tkp.controller.aoptest.UserServiceHelper
        userService.search();
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM