zoukankan      html  css  js  c++  java
  • [原创]java WEB学习笔记104:Spring学习---AOP 前奏,通过一个问题引入动态代理

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用

    内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系。

    本人互联网技术爱好者,互联网技术发烧友

    微博:伊直都在0221

    QQ:951226918

    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    问题引入

      

    1.实现

    原始实现方式:

     1 package com.jason.spring.aop.helloworld;
     2 
     3 public interface ArithmeticCaculator {
     4     
     5     int add(int i, int j);
     6     int sub(int i, int j);
     7     
     8     int mul(int i, int j);
     9     int div(int i, int j);
    10     
    11 }
    ArithmeticCaculator
     1 package com.jason.spring.aop.helloworld;
     2 
     3 public class fArithmeticCaculatorloggingImpl implements ArithmeticCaculator {
     4 
     5     @Override
     6     public int add(int i, int j) {
     7         System.out.println("the method add begins with [" + i + ", " + j + "]");
     8         int result = i + j;
     9         System.out.println("the method add end with " + result);
    10         return result;
    11     }
    12 
    13     @Override
    14     public int sub(int i, int j) {
    15         System.out.println("the method sub begins with [" + i + ", " + j + "]");
    16         int result = i - j;
    17         System.out.println("the method sub end with " + result);
    18         return result;
    19     }
    20 
    21     @Override
    22     public int mul(int i, int j) {
    23         System.out.println("the method mul begins with [" + i + ", " + j + "]");
    24         int result = i * j;
    25         System.out.println("the method mul end with " + result);
    26         return result;
    27     }
    28 
    29     @Override
    30     public int div(int i, int j) {
    31         System.out.println("the method div begins with [" + i + ", " + j + "]");
    32         int result = i / j;
    33         System.out.println("the method div end with " + result);
    34         return result;
    35     }
    36 
    37 }
    fArithmeticCaculatorloggingImpl

    问题:

      1).代码混乱:越来越多的非业务需求(日志和验证等)加入后, 原有的业务方法急剧膨胀.  每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点.

      2).代码分散: 以日志需求为例, 只是为了满足这个单一需求, 就不得不在多个模块(方法)里多次重复相同的日志代码. 如果日志需求发生变化, 必须修改所有模块.

    解决方式:动态代理

      思想:代理设计模式的原理: 使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时将方法调用转到原始对象上.

          

    2. 手动通过动态代理实现(实际开发中不推荐,因为难度较高)

     1 package com.jason.spring.aop.helloworld;
     2 
     3 import java.lang.reflect.Method;
     4 import java.util.Arrays;
     5 
     6 import org.springframework.cglib.proxy.InvocationHandler;
     7 import org.springframework.cglib.proxy.Proxy;
     8 
     9 public class ArithmeticCaculatorLoggingProxy {
    10     
    11     //要代理的对象
    12     private ArithmeticCaculator target;
    13     
    14      public ArithmeticCaculatorLoggingProxy(ArithmeticCaculator target) {
    15         this.target = target;
    16     }
    17     
    18     
    19     
    20     public ArithmeticCaculator getLoggingProxy(){
    21         ArithmeticCaculator proxy = null;
    22         
    23         //代理对象由哪一个类加载器负责加载
    24         ClassLoader loader = target.getClass().getClassLoader();
    25         
    26         //代理对象的类型,即其中有那些方法
    27         Class[] interfaces = new Class[]{ArithmeticCaculator.class};
    28         
    29         //当调用代理对象,其中的方法时,该执行的代码
    30         InvocationHandler invocationHandler = new InvocationHandler() {
    31             /**
    32              * proxy:正在返回的那个代理对象,一般情况下,在invoke 方法中都不使用对象
    33              * method:正在被调用的方法
    34              * args:调用方法时,传入的参数
    35              */
    36             @Override
    37             public Object invoke(Object proxy, Method method, Object[] args)
    38                     throws Throwable {
    39                 String methodName = method.getName();
    40                 
    41                 //日志
    42                 System.out.println("The method " + methodName + "begins with " + Arrays.asList(args));
    43                 //执行方法
    44                 Object result = method.invoke(target, args);
    45                 //日志
    46                 System.out.println("The method " + methodName + "end with " + result);
    47                 return result;
    48             }
    49         };
    50         
    51         proxy =(ArithmeticCaculator) Proxy.newProxyInstance(loader, interfaces, invocationHandler);
    52                 
    53                 
    54         return proxy;
    55     }
    56     
    57 }

    测试

    Main.java

     1 package com.jason.spring.aop.helloworld;
     2 
     3 public class Main {
     4 
     5     public static void main(String[] args) {
     6         /*ArithmeticCaculator arithmeticCaculator = null;
     7         arithmeticCaculator  = new ArithmeticCaculatorImpl();*/
     8         
     9         ArithmeticCaculator target = new ArithmeticCaculatorImpl();
    10         ArithmeticCaculator proxy = new ArithmeticCaculatorLoggingProxy(target).getLoggingProxy();
    11         
    12         
    13         int result = proxy.add(1, 2);
    14         System.out.println("--> " + result);
    15         
    16         result = proxy.sub(1, 2);
    17         System.out.println("--> " + result);
    18     }
    19     
    20 }

    3.简便方式:使用springAOP  原理 见下一节 105

       

     1 package com.jason.spring.aop.impl;
     2 
     3 public interface ArithmeticCaculator {
     4     
     5     int add(int i, int j);
     6     int sub(int i, int j);
     7     
     8     int mul(int i, int j);
     9     int div(int i, int j);
    10     
    11 }
    ArithmeticCaculator
     1 package com.jason.spring.aop.impl;
     2 
     3 import org.springframework.stereotype.Component;
     4 
     5 
     6 @Component
     7 public class ArithmeticCaculatorImpl implements ArithmeticCaculator {
     8 
     9     @Override
    10     public int add(int i, int j) {
    11         int result = i + j;
    12         return result;
    13     }
    14 
    15     @Override
    16     public int sub(int i, int j) {
    17         int result = i - j;
    18         return result;
    19     }
    20 
    21     @Override
    22     public int mul(int i, int j) {
    23         int result = i * j;
    24         return result;
    25     }
    26 
    27     @Override
    28     public int div(int i, int j) {
    29         int result = i / j;
    30         return result;
    31     }
    32 
    33 }
    ArithmeticCaculatorImpl
     1 package com.jason.spring.aop.impl;
     2 
     3 import java.util.Arrays;
     4 import java.util.List;
     5 
     6 import org.aspectj.lang.JoinPoint;
     7 import org.aspectj.lang.annotation.After;
     8 import org.aspectj.lang.annotation.Aspect;
     9 import org.aspectj.lang.annotation.Before;
    10 import org.springframework.stereotype.Component;
    11 
    12 
    13 //把这个类声明为一个切面
    14 //1.需要将该类放入到IOC 容器中
    15 @Component
    16 //2.再声明为一个切面
    17 @Aspect
    18 public class LoggingAspect {
    19     
    20     //声明该方法是一个前置通知:在目标方法开始之前执行 哪些类,哪些方法
    21     //作用:@before 当调用目标方法,而目标方法与注解声明的方法相匹配的时候,aop框架会自动的为那个方法所在的类生成一个代理对象,在目标方法执行之前,执行注解的方法
    22     //支持通配符
    23     //@Before("execution(public int com.jason.spring.aop.impl.ArithmeticCaculatorImpl.*(int, int))")
    24     @Before("execution(* com.jason.spring.aop.impl.*.*(int, int))")
    25     public void beforeMethod(JoinPoint joinPoint){
    26         String methodName = joinPoint.getSignature().getName();
    27         List<Object> args = Arrays.asList(joinPoint.getArgs());
    28         System.out.println("The method " + methodName + " begins " + args);
    29     }
    30     
    31     @After("execution(* com.jason.spring.aop.impl.*.*(int, int))")
    32     public void fterMethod(JoinPoint joinPoint){
    33         String methodName = joinPoint.getSignature().getName();
    34         List<Object> args = Arrays.asList(joinPoint.getArgs());
    35         System.out.println("The method " + methodName + " end " + args);
    36     }
    37     
    38     
    39 }
    LoggingAspect
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:aop="http://www.springframework.org/schema/aop"
     5     xmlns:context="http://www.springframework.org/schema/context"
     6     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
     7         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
     8         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
     9 
    10 
    11     <!-- 配置自动扫描的包 -->
    12     <context:component-scan base-package="com.jason.spring.aop.impl"></context:component-scan>
    13     
    14     <!-- 使 AspjectJ 注解作用:自动为匹配的类生成代理对象 -->
    15     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    16 
    17 </beans>
    aop.xml
     1 package com.jason.spring.aop.impl;
     2 
     3 import org.springframework.context.ApplicationContext;
     4 import org.springframework.context.support.ClassPathXmlApplicationContext;
     5 
     6 public class Main {
     7     
     8     public static void main(String[] args) {
     9         
    10         //1.创建Spring 的IOC 容器
    11         ApplicationContext ctx = new ClassPathXmlApplicationContext("aop.xml");
    12         
    13         //2.从IOC 容器中获取 bean实例
    14         ArithmeticCaculator arithmeticCaculator = (ArithmeticCaculator) ctx.getBean(ArithmeticCaculator.class);
    15         
    16         //3.使用bean
    17         int result = arithmeticCaculator.add(1, 2);
    18         System.out.println(result);
    19         
    20          result = arithmeticCaculator.div(1, 2);
    21         System.out.println(result);
    22         
    23         
    24     }
    25 
    26 }
    Main
  • 相关阅读:
    jpype
    Java获取类中的所有方法
    SQL中INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN区别
    如何用命令将本地项目上传到git
    Java连接Mysql:通过配置文件
    lsof -i:port_number
    yum install lsof
    Git的基本使用方法(受益匪浅)
    [后端]gitlab之gitlab-ci自动部署
    centos7安装redis-4.0.1集群
  • 原文地址:https://www.cnblogs.com/jasonHome/p/6071911.html
Copyright © 2011-2022 走看看