精华内容
下载资源
问答
  • 通知方法基础使用方法 package com.fang.log; import java.lang.reflect.Method; import java.util.Arrays; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org....

    通知方法的基础使用方法

    package com.fang.log;
    
    import java.lang.reflect.Method;
    import java.util.Arrays;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    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.springframework.stereotype.Component;
    
    @Aspect
    @Component
    public class LogUtils {
    	
    	  //抽取出可重用的切入点表达式
    	  @Pointcut("execution(public int com.fang.imp.ImpCalculator.*(int, int))")
    	  public void Myprocess() {};
    
    	  //@Before:在方法调用之前调用,value:使用抽取出的切入点表达式
    	  @Before(value="Myprocess()") 
    	  public static void logStart(JoinPoint joinpoint) {
    		  Object []args =joinpoint.getArgs();
    		  System.out.println(""+joinpoint.getSignature().getName()+""+"方法开始执行,"+"参数是:"+Arrays.asList(args)); 
    	  }
    	  
    	  //@AfterReturning:方法调用完成之后返回参数,return:设置返回参数
    	  @AfterReturning(value="Myprocess()",returning ="result") 
    	  public static void logReturn(JoinPoint joinpoint , Object result) {
    		  System.out.println(""+joinpoint.getSignature().getName()+""+"方法结束执行,"+"结果是:"+result); 
    	  }
    	  
    	  //@AfterThrowing:方法异常产生时调用,throwing:设置抛出异常
    	  @AfterThrowing(value="Myprocess()",throwing="e") 
    	  public static void errorss(JoinPoint joinpoint , Exception e) {
    	  System.out.println(joinpoint.getSignature().getName()+"有异常产生:"+e);
    	  
    	  }
    }
    

    环绕通知的使用方法

    package com.fang.log;
    
    import java.lang.reflect.Method;
    import java.util.Arrays;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    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.springframework.stereotype.Component;
    
    @Aspect
    @Component
    public class LogUtils {
    	
    	  //抽取出可重用的切入点表达式
    	  @Pointcut("execution(public int com.fang.imp.ImpCalculator.*(int, int))")
    	  public void Myprocess() {};
    
    	@Around(value = "Myprocess()")
    	public Object AroundAdvice(ProceedingJoinPoint pcj) {
    		Object []args = pcj.getArgs();
    		String name = pcj.getSignature().getName();
    		Object result =null;
    		try {
    		    //@Before
    			System.out.println("环绕通知的"+name+"方法开始执行");
    			//就是使用反射调用目标方法,相当于method.invoke(calculator, args);
    			result = pcj.proceed(args);
    			//@AfterReturning
    			System.out.println("环绕通知的"+name+"方法执行返回,值是"+result);
    		} catch (Throwable e) {
    		    //@AfterThrowing
    			System.out.println("执行方法的时候发生了异常"+e);
    		}finally {
    		    //@After
    			System.out.println("环绕通知的"+name+"方法执行结束");
    		}
    		
    		return result;
    	}
    }
    
    展开全文
  • 声明一个通知类 同时继承MethodBeforeAdvice、AfterReturningAdvice和MethodInterceptor package com.zx.aop; import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInterceptor; import ...

    声明一个通知类 同时继承MethodBeforeAdvice、AfterReturningAdvice和MethodInterceptor

    package com.zx.aop;
    
    
    import java.lang.reflect.Method;
    
    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    import org.springframework.aop.AfterReturningAdvice;
    import org.springframework.aop.MethodBeforeAdvice;
    
    public class MyMethodAdvice implements MethodBeforeAdvice,AfterReturningAdvice,MethodInterceptor {
    	@Override
    	public void before(Method method, Object[] args, Object target) throws Throwable {
    		// TODO Auto-generated method stub
    		System.out.println("前置通知");
    	}
    
    	@Override
    	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
    		// TODO Auto-generated method stub
    		System.out.println("后置通知");
    	}
    	 
    	@Override
    	public Object invoke(MethodInvocation invocation) throws Throwable {
    		// TODO Auto-generated method stub
    		System.out.println("调用方法前");
    		Object proceed = invocation.proceed();
    		System.out.println("调用方法后");
    		return proceed;
    	}
    
    }
    

    配置xml

    	<!-- 1.配置被代理的对象 -->
    	<bean id="test1Service" class="com.zx.aop.Test1Service">
    		<property name="name" value='zx'></property>
    	</bean>
    	<!-- 2.配置通知对象 -->
    	<bean id="myMethodAdvice" class="com.zx.aop.MyMethodAdvice">
    	</bean>
    	<!-- <bean id="MyMethodInterceptor" class="com.zx.aop.MyMethodInterceptor">
    	</bean> -->
    	<!-- 3.配置代理对象   -->
    	<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
    	<!-- 配置代理接口  代理对象将实现代理的接口 可以不设置-->
    	<!-- <property name="proxyInterfaces">
    		<list>
    			<value>com.zx.aop.TestServiceTnter</value>
    		</list>
    	</property> -->
    	<!-- 4.把通知织入代理对象 可以是list -->
    	<property name="interceptorNames">
    	<list>
    	<value>myMethodAdvice</value>
    <!-- 	<value>MyMethodInterceptor</value> -->
    	</list>
    	</property>
    	<!-- 5.配置被代理对象 必须要有 -->
    	<property name="target" ref="test1Service"></property>
    	</bean>

    运行代码

    TestServiceTnter ts1=(TestServiceTnter) context.getBean("proxyFactoryBean");
    		ts1.sayHello();
    输出

    调用方法前
    前置通知
    Hello zx
    后置通知
    调用方法后


    将前置通知后置通知与环绕通知类分开实现

    前置加后置类

    package com.zx.aop;
    
    
    import java.lang.reflect.Method;
    
    import org.springframework.aop.AfterReturningAdvice;
    import org.springframework.aop.MethodBeforeAdvice;
    
    public class MyMethodAdvice implements MethodBeforeAdvice,AfterReturningAdvice {
    	@Override
    	public void before(Method method, Object[] args, Object target) throws Throwable {
    		// TODO Auto-generated method stub
    		System.out.println("前置通知");
    	}
    
    	@Override
    	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
    		// TODO Auto-generated method stub
    		System.out.println("后置通知");
    	}
    	
    }
    

    环绕通知类

    package com.zx.aop;
    
    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    
    public class MyMethodInterceptor implements MethodInterceptor {
    
    	@Override
    	public Object invoke(MethodInvocation invocation) throws Throwable {
    		// TODO Auto-generated method stub
    		System.out.println("调用方法前");
    		Object proceed = invocation.proceed();
    		System.out.println("调用方法后");
    		return proceed;
    	}
    
    }
    

    配置xml

    <!-- 1.配置被代理的对象 -->
    	<bean id="test1Service" class="com.zx.aop.Test1Service">
    		<property name="name" value='zx'></property>
    	</bean>
    	<!-- 2.配置通知对象 -->
    	<bean id="myMethodAdvice" class="com.zx.aop.MyMethodAdvice">
    	</bean>
    	<bean id="MyMethodInterceptor" class="com.zx.aop.MyMethodInterceptor">
    	</bean>
    	<!-- 3.配置代理对象   -->
    	<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
    	<!-- 配置代理接口  代理对象将实现代理的接口 可以不设置-->
    	<!-- <property name="proxyInterfaces">
    		<list>
    			<value>com.zx.aop.TestServiceTnter</value>
    		</list>
    	</property> -->
    	<!-- 4.把通知织入代理对象 可以是list -->
    	<property name="interceptorNames">
    	<list>
    	<value>myMethodAdvice</value>
    	<value>MyMethodInterceptor</value>
    	</list>
    	</property>
    	<!-- 5.配置被代理对象 必须要有 -->
    	<property name="target" ref="test1Service"></property>
    	</bean>

    运行代码不变 运行结果

    前置通知
    调用方法前
    Hello zx
    调用方法后
    后置通知

    更改xml中interceptorNames属性中两个通知类的顺序 再次运行 结果如下

    调用方法前
    前置通知
    Hello zx
    后置通知
    调用方法后

    展开全文
  • 环绕通知前 这是前置通知one!请求目标方法名:findAll 这是actionfindAll方法执行。。。 在DAO中查找商品findAll方法。。。。 Hibernate: select this_.pid as pid1_0_0_, this_.pname as pname2_...
  • 使用注解AOP实现方法日志记录,免去重复写日志存储麻烦。该方案能记录方法请求参数,返回结果等信息 代码结构: 1.自定义注解 package com.example.demo.aop; import java.lang.annotation.ElementType; ...

    使用注解AOP实现方法日志记录,免去重复写日志存储的麻烦。该方案能记录方法请求参数,返回结果等信息

    代码结构:

    1.自定义注解

    package com.example.demo.aop;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 在方法上使用该注解时,Spring会自动存储被注解方法的请求参数和返回信息到log表
     * 存储的基础字段包括:
     *      businessItemId:方法名称
     *      requestParameter:请求的参数名称以及参数值
     *      responseContent:请求的返回
     *      result:如果程序正常运行则存储success,否则存储failure
     *      types:传参中的logType(根据注解中的传参决定,非必填)
     *      typesName:types对应的名称
     *      businessId:传参中的businessId字段(根据注解中的传参决定,非必填)
     *      createTime:创建时间
     *      updateTime:更新时间
     *      note:如果程序异常执行,note字段存储e.getMessage()
     * @author shengsheng
     */
    // 方法注解
    @Target(ElementType.METHOD)
    // 运行时可见
    @Retention(RetentionPolicy.RUNTIME)
    public @interface LogAnno {
        /**
         * log的types字段
         * @return
         */
        String logType() default "";
    
        /**
         * log的businessId字段
         * @return
         */
        String businessId() default "";
    }

    2.切面实现

    package com.example.demo.aop;
    
    import com.alibaba.fastjson.JSON;
    import com.example.demo.entity.Log;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.core.DefaultParameterNameDiscoverer;
    import org.springframework.core.ParameterNameDiscoverer;
    import org.springframework.stereotype.Component;
    import org.springframework.util.StringUtils;
    
    import java.lang.reflect.Method;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Log的AOP实现日志
     * @author shengsheng
     *
     */
    @Component
    @Aspect
    public class LogAspect {
    
        /*@Autowired
        private LogMapper logMapper;*/
    
        @Pointcut("@annotation(com.example.demo.aop.LogAnno)")
        public void logPointCut() {
        }
    
        /**
         * 环绕通知记录日志通过注解匹配到需要增加日志功能的方法
         * @param pjp
         * @return
         * @throws Throwable
         */
        @Around("logPointCut()")
        public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
            Log log = new Log();
            Signature signature = pjp.getSignature();
            MethodSignature methodSignature = (MethodSignature)signature;
            // 1.方法执行前的处理,相当于前置通知
           // 获取正在访问的类
            Class executionClass = pjp.getTarget().getClass();
            // 获取访问的方法的名称
            String methodName = pjp.getSignature().getName();
            // 获取正在访问的方法
            Method executionMethod =methodSignature.getMethod();
            // 获取访问的方法的参数
            Object[] args = pjp.getArgs();
            //获取方法中的参数名称
            ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
            String[] parameterNames = pnd.getParameterNames(executionMethod);
            log.setBusinessItemId(methodName);
            if((parameterNames!=null)&&(parameterNames.length>0)&&(args!=null)&&(args.length>0)){
                Map<String,Object> requestParams = new HashMap<>(args.length);
                for (int i = 0 ;i<parameterNames.length;i++) {
                    requestParams.put(parameterNames[i],args[i]);
                }
                //设置请求参数
                log.setRequestParameter(JSON.toJSONString(requestParams));
            }
            LogAnno annotation = executionMethod.getAnnotation(LogAnno.class);
            //获取注解中的types字段
            String logTypeStr = annotation.logType();
            if(!StringUtils.isEmpty(logTypeStr)){
                Integer logType = Integer.valueOf(logTypeStr);
                log.setTypes(logType);
                log.setTypesName("");
            }
            String businessId = annotation.businessId();
            log.setBusinessId(businessId);
            Object result = null;
            try {
                //让代理方法执行
                result = pjp.proceed();
                // 2.后置通知
                log.setResult("success");
            } catch (Exception e) {
                // 3.异常通知
                log.setResult("failure");
                log.setNote(e.getMessage());
            } finally {
                // 4.最终通知
                Date now = new Date();
                log.setCreateTime(now);
                log.setResponseContent(JSON.toJSONString(result));
                log.setUpdateTime(now);
                System.out.println(log);
                //入库
    //            logMapper.insertSelective(log);
            }
            return result;
        }
    }

    3.在方法上使用注解

    package com.example.demo.utils;
    
    import com.example.demo.aop.LogAnno;
    import org.springframework.stereotype.Component;
    
    /**
     * description:
     *
     * @author shengsheng
     * @date 2020/9/24 16:32
     */
    @Component
    public class CalculateUtils {
    
        //使用注解
        @LogAnno(logType = "1",businessId = "div")
        public Integer div(Integer a,Integer b){
            return a/b;
        }
    }
    

    4.测试

    package com.example.demo.test;
    
    import com.example.demo.utils.CalculateUtils;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    /**
     * description:
     *
     * @author shengsheng
     * @date 2020/9/24 16:48
     */
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class CalculateTest {
        @Autowired
        private CalculateUtils calculateUtils;
        @Test
        public void test() {
            Integer div = calculateUtils.div(1, 1);
            System.out.println(div);
        }
    }
    

    5.测试结果

    Log{id=null, types=1, typesName='', businessId='div', businessItemId='div', result='success', requestParameter='{"a":1,"b":1}', responseContent='1', note='null', createTime=Thu Sep 24 17:12:57 CST 2020, updateTime=Thu Sep 24 17:12:57 CST 2020}
    

     

    展开全文
  • •AspectJ:Java 社区里最完整最流行 AOP 框架. •在 Spring2.0以上版本中, 可以使用基于 AspectJ注解或基于 XML 配置 AOP •要在 Spring 应用中使用 AspectJ注解, 必须在 classpath下包含 AspectJ类库: aop...

    1.(AspectJ

     

    AspectJJava 社区里最完整最流行的 AOP 框架.

    Spring2.0以上版本, 可以使用基于 AspectJ注解或基于 XML 配置的 AOP

    要在 Spring 应用中使用 AspectJ注解, 必须在 classpath下包含 AspectJ类库: aopalliance.jaraspectj.weaver.jar spring-aspects.jar

    aop Schema 添加到 <beans> 根元素中.

    Spring IOC 容器中启用 AspectJ注解支持, 只要Bean 配置文件中定义一个空的 XML 元素 <aop:aspectj-autoproxy>

    SpringIOC 容器侦测到 Bean 配置文件中的 <aop:aspectj-autoproxy> 元素时, 会自动为与 AspectJ切面匹配的 Bean 创建代理.

    要在 Spring 中声明 AspectJ切面, 只需要在 IOC 容器中将切面声明为 Bean 实例. 当在 Spring IOC 容器中初始化 AspectJ切面之后, Spring IOC 容器就会为那些与 AspectJ切面相匹配的 Bean 创建代理.

    AspectJ注解中, 切面只是一个带有 @Aspect 注解的 Java .

    通知是标注有某种注解的简单的 Java 方法.

    AspectJ支持 5 种类型的通知注解:

    @Before: 前置通知, 在方法执行之前执行

    @After: 后置通知, 在方法执行之后执行

    @AfterRunning: 返回通知, 在方法返回结果之后执行

    @AfterThrowing: 异常通知, 在方法抛出异常之后

    @Around: 环绕通知, 围绕着方法执行

    1.1(前置通知)

     

    前置通知:在方法执行之前执行的通知

    前置通知使用 @Before 注解, 并将切入点表达式的值作为注解值.

    可以在通知方法中声明一个类型为 JoinPoint的参数. 然后就能访问链接细节.

    1.2(后置通知)

     

    后置通知是在连接点完成之后执行的, 即连接点返回结果或者抛出异常的时候, 下面的后置通知记录了方法的终止.

    一个切面可以包括一个或者多个通知.使用@After注解

    1.3(返回通知)

     

    无论连接点是正常返回还是抛出异常, 后置通知都会执行. 如果只想在连接点返回的时候做记录, 应使用返回通知代替后置通知.

    在返回通知中, 只要将 returning属性添加到 @AfterReturning注解中, 就可以访问连接点的返回值. 该属性的值即为用来传入返回值的参数名称.

    必须在通知方法的签名中添加一个同名参数. 在运行时, Spring AOP 会通过这个参数传递返回值.

     

    1.4(异常通知)

     

    只在连接点抛出异常时才执行异常通知

    throwing 属性添加到 @AfterThrowing注解中, 也可以访问连接点抛出的异常. Throwable是所有错误和异常类的超类. 所以在异常通知方法可以捕获到任何错误和异常.

    如果只对某种特殊的异常类型感兴趣, 可以将参数声明为其他异常的参数类型. 然后通知就只在抛出这个类型及其子类的异常时才被执行.

     

    1.5(环绕通知(类似于动态代理))

     

    环绕通知是所有通知类型中功能最为强大的, 能够全面地控制连接点. 甚至可以控制是否执行连接点.

    对于环绕通知来说, 连接点的参数类型必须是 ProceedingJoinPoint . 它是 JoinPoint的子接口, 允许控制何时执行, 是否执行连接点.

    在环绕通知中需要明确调用 ProceedingJoinPointproceed() 方法来执行被代理的方法. 如果忘记这样做就会导致通知被执行了, 但目标方法没有被执行.

    注意: 环绕通知的方法需要返回目标方法执行之后的结果, 即调用 joinPoint.proceed(); 的返回值, 否则会出现空指针异常

     

    2.(代码说明)

     

    2.1(目标方法所在的bean)

     

    package com.spring.aop;
    
    public interface ArithmeticCalculator {
    
       int add(int i, int j);
       int sub(int i, int j);
       
       int mul(int i, int j);
       int div(int i, int j);
       
    }
    
    
     
    package com.spring.aop;
    
    import org.springframework.stereotype.Component;
    
    @Component("arithmeticCalculator")
    public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
    
       @Override
       public int add(int i, int j) {
          int result = i + j;
          return result;
       }
    
       @Override
       public int sub(int i, int j) {
          int result = i - j;
          return result;
       }
    
       @Override
       public int mul(int i, int j) {
          int result = i * j;
          return result;
       }
    
       @Override
       public int div(int i, int j) {
          int result = i / j;
          return result;
       }
    
    }
    

     

    2.2(切面)

     

    package com.spring.aop;
    
    import java.util.Arrays;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;
    
    /**
     * AOP 的配置顺序
     * 1. 加入 jar 包
     * com.springsource.net.sf.cglib-2.2.0.jar
     * com.springsource.org.aopalliance-1.0.0.jar
     * com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
     * spring-aspects-4.0.0.RELEASE.jar
     *
     * 2. 在 Spring 的配置文件中加入 aop 的命名空间。
     *
     * 3. 基于注解的方式来使用 AOP
     * 3.1 在配置文件中配置自动扫描的包: <context:component-scan base-package="com.spring.aop"></context:component-scan>
     * 3.2 加入使 AspjectJ 注解起作用的配置: <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
     * 为匹配的类自动生成动态代理对象.
     *
     * 4. 编写切面类:
     * 4.1 一个一般的 Java 类
     * 4.2 在其中添加要额外实现的功能.
     *
     * 5. 配置切面
     * 5.1 切面必须是 IOC 中的 bean: 实际添加了 @Component 注解
     * 5.2 声明是一个切面: 添加 @Aspect
     * 5.3 声明通知: 即额外加入功能对应的方法.
     * 5.3.1 前置通知: @Before("execution(public int com.spring.aop.ArithmeticCalculator.*(int, int))")
     * @Before 表示在目标方法执行之前执行 @Before 标记的方法的方法体.
     * @Before 里面的是切入点表达式:
     *
     * 6. 在通知中访问连接细节: 可以在通知方法中添加 JoinPoint 类型的参数, 从中可以访问到方法的签名和方法的参数.
     *
     * 7. @After 表示后置通知: 在方法执行之后执行的代码.
     */
    
    //通过添加 @Aspect 注解声明一个 bean 是一个切面!
    //需要把该类放入到IOC容器中,再声明为一个切面
    @Aspect
    @Component
    public class LoggingAspect {
    
       @Before("execution(public int com.spring.aop.ArithmeticCalculator.*(int, int))")
       public void beforeMethod(JoinPoint joinPoint){
          String methodName = joinPoint.getSignature().getName();
          Object [] args = joinPoint.getArgs();
    
          System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));
       }
    //后置通知:在目标方法执行后(无论是否发生异常),执行的通知
    //在后置通知中还不能访问目标方法执行的结果,需要在返回通知里面去访问目标方法的返回通知
       @After("execution(* com.spring.aop.*.*(..))")
       public void afterMethod(JoinPoint joinPoint){
          String methodName = joinPoint.getSignature().getName();
          System.out.println("The method " + methodName + " ends");
       }
       /**
        * 定义一个方法, 用于声明切入点表达式. 一般地, 该方法中再不需要添入其他的代码.
        * 使用 @Pointcut 来声明切入点表达式.
        * 后面的其他通知直接使用方法名来引用当前的切入点表达式.
        */
       @Pointcut("execution(public int com.spring.aop.ArithmeticCalculator.*(..))")
       public void declareJointPointExpression(){}
       /**
        * 在方法法正常结束受执行的代码
        * 返回通知是可以访问到方法的返回值的!
        */
       @AfterReturning(value="declareJointPointExpression()",
             returning="result")
       public void afterReturning(JoinPoint joinPoint, Object result){
          String methodName = joinPoint.getSignature().getName();
          System.out.println("The method " + methodName + " ends with " + result);
       }
    
       /**
        * 在目标方法出现异常时会执行的代码.
        * 可以访问到异常对象; 且可以指定在出现特定异常时在执行通知代码
        */
       @AfterThrowing(value="declareJointPointExpression()",
             throwing="e")
       public void afterThrowing(JoinPoint joinPoint, Exception e){
          String methodName = joinPoint.getSignature().getName();
          System.out.println("The method " + methodName + " occurs excetion:" + e);
       }
    
       /**
        * 环绕通知需要携带 ProceedingJoinPoint 类型的参数.
        * 环绕通知类似于动态代理的全过程: ProceedingJoinPoint 类型的参数可以决定是否执行目标方法.
        * 且环绕通知必须有返回值, 返回值即为目标方法的返回值
        */
       /*
       @Around("execution(public int com.spring.aop.ArithmeticCalculator.*(..))")
       public Object aroundMethod(ProceedingJoinPoint pjd){
    
          Object result = null;
          String methodName = pjd.getSignature().getName();
    
          try {
             //前置通知
             System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs()));
             //执行目标方法
             result = pjd.proceed();
             //返回通知
             System.out.println("The method " + methodName + " ends with " + result);
          } catch (Throwable e) {
             //异常通知
             System.out.println("The method " + methodName + " occurs exception:" + e);
             throw new RuntimeException(e);
          }
          //后置通知
          System.out.println("The method " + methodName + " ends");
    
          return result;
       }
       */
    
    }
    

    2.3(xml配置文件)

     

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
       <!-- 自动扫描的包 -->
       <context:component-scan base-package="com.spring.aop"></context:component-scan>
    
       <!-- 使 AspectJ 的注解起作用 -->
       <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
    </beans>
    

    2.4(Main)

     

    package com.spring.aop;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Main {
       
       public static void main(String[] args) {
          ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-aop.xml");
          ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator) ctx.getBean("arithmeticCalculator");
          System.out.println(arithmeticCalculator.getClass().getName());
          int result = arithmeticCalculator.add(11, 12);
          System.out.println("result:" + result);
          result = arithmeticCalculator.div(21, 3);
          System.out.println("result:" + result);
    
       }
       
    }
    

    2.5(运行结果)

                         

    2.6(总结)

    通过上面的步骤以及运行结果我们可发现,运行的过程有点像动态代理,Spring的IOC在生成切面的时候会根据切点找到对应的bean,然后为其生成代理对象

    3.(切面的优先级)

     

    在同一个连接点上应用不止一个切面时, 除非明确指定, 否则它们的优先级是不确定的.

    切面的优先级可以通过实现 Ordered 接口或利用 @Order 注解指定.

    若使用 @Order 注解, 序号出现在注解中

                                  

                                   

    4.(重用切入点定义)

     

    在编写 AspectJ切面时, 可以直接在通知注解中书写切入点表达式. 但同一个切点表达式可能会在多个通知中重复出现.

    AspectJ切面中, 可以通过 @Pointcut注解将一个切入点声明成简单的方法. 切入点的方法体通常是空的, 因为将切入点定义与应用程序逻辑混在一起是不合理的.

    切入点方法的访问控制符同时也控制着这个切入点的可见性. 如果切入点要在多个切面中共用, 最好将它们集中在一个公共的类中. 在这种情况下, 它们必须被声明为 public. 在引入这个切入点时, 必须将类名也包括在内. 如果类没有与这个切面放在同一个包中, 还必须包含包名.

    其他通知可以通过方法名称引入该切入点.

    展开全文
  •  AspectJ:Java社区里最完整最流行AOP框架  在Spring2.0以上版本中,可以使用基于AspectJ注解或基于XML配置AOP 在Spring中启用AspectJ注解支持  要在Spring应用中使用AspectJ注解,必须在classpath下...
  • Spring AOPAspectJ:(Java社区里最完整最流行AOP框架)spring自身也有一套AOP框架,但相比较于AspectJ,更推荐AspectJ在Spring2.0以上版本中,可以使用基于AspectJ注解或基于XML配置AOP。基于AspectJ注解:用...
  • Spring XML文件写法与1中一样,请参考使用Spring注解方试实现AOP1同样一相java类:package com.sszd.db;public class DbOpretor { public void insert(String sql)//带参数 { System.out.println("insert...
  • 使用@Aspect 注解类, Spring 将会把它当作一个特殊Bean(一个切面,也就是不对这个类本身进行动态代理)。 4,在头信息中加入注解@Component,将这个类放入容器中。 @component (把普通pojo实例化到spring...
  • 新建一个包,并且将aop包下面所有java文件全部拷过来 删除注解 新建一个spring配置文件 修改测试类main中使用的xml文件 在xml中像配置普通bean一样配置三个bean 配置aop 配置切点表达式 填充execution()...
  • spring中通知分为以下几种:before:前置通知,在方法执行之前执行around:环绕通知,在方法执行前后执行afterreturning:在方法执行成功后执行afterthrowning:异常通知,在方法发生异常后执行after:后置通知,在...
  • SpringAOP的五种通知的配置及使用

    千次阅读 2016-11-15 08:36:48
    1.Spring有五种通知类型本文着重讲述3中:前置通知,后置通知,环绕通知。 2.前置通知:在运行目标方法之前运行。 2.1:前置通知的配置:第一步:新建一个类,实现MethodBeforeAdvice接口,并且复写其中的before方法...
  • org.aopalliance.intercept.MethodInterceptor(环绕通知): 在目标方法执行前后实施增强,用于日志、事务管理等。 org.springframework.aop.MethodBeforeAdvice(前置通知): 在目标方法执行前实施增强,用于权限...
  • 关键字 @controllerAdvice 中包含了@component组件,所以能被扫描到 @aspect切面、@pointCut切入点、@before前置... 非环绕通知参数joinpoint、环绕通知参数proceedingjoinpoint、注解参数、返回值参数Object、thro
  • 废话不多说,相信点进这篇博客的看客需求肯定是需要动态的使用代码进行修改注解的值,可能看了很多博客,尝试了很多方法,都没有实现。那么恭喜你,马上就可以实现了,只要你耐心的花上一点点时间看我这篇博客即可。...
  • 前置通知(@Before)和后置通知(@After)有着一些...通过环绕通知,我们可以在一个方法内完成前置、后置、异常(@AfterThrowing)等通知所实现功能。由于这些实现都是在同一个方法内,这样就不需要通过类成员...
  • 空间音频最早出现在苹果 2020 年发布 iOS 14 上,使用支持空间音频设备,可以感受到声音从 360 度方向传来,实现更沉浸的环绕立体声效果。如今这一功能,Android 12 用户也能享受了。 Android 12 支持最新 ...
  • 首页专栏java文章详情0AOP与Redis缓存实现JayX发布于 今天 12:091. AOP实现缓存业务1.1 业务需求1).... 利用AOP 拦截注解 利用环绕通知方法实现业务1.2 自定义注解@CacheFind1.3 注解标识1.4 编辑AOPp...
  • Java_SpringMVC_day01

    2020-09-19 21:12:02
    回顾 ...@Around 环绕通知 开启aop注解驱动: <aop:aspectj-autoproxy /> aop原理: 默认是判断是否实现接口,实现使用的是jdk动态代理,没有实现使用CGLIB代理。 我们也可以通过设置使无论是
  • spring 的环绕通知(advice)可以在某一任务开始前和结束后执行一些增强方法。所以可以使用这一特性来计算任务耗时。 程序结构: CountTime.java -- 通知类(advice) CopyFile.java -- 连接点(jointPoint) ...
  • Java Mail结合AOP实现库存预警

    千次阅读 2019-02-25 10:48:31
    思路:在每次售出商品时会对库存数据进行修改,此时在已有方法中会返回一个带有仓库所有数据列表结合AOP思想,于是在此处采用环绕通知获取该方法返回值,并对返回值进行判断是否需要发送邮件。 关于AOP...
  • Spring AOP 介绍与简单DEMO 通知(Advice) Spring中的切面一共提供5种通知的... 环绕通知(@Around) 前面4个较为容易理解,例如“前置通知”,我们通常在一个方法的第一句打印出传入的方法参数,此时就可以使用...
  • 目录 一:java Web项目中日志系统 二:日志系统分类 三:springboot整合slf4j 1.添加mavne支持 2.配置xml以及制定yml ...3.环绕通知封装日志对象 4.说明 一:java Web项目中日志系统 ...
  • 环绕通知1.xml配置,在aspect里面2. 方法使用 一.概念 连接点: 如service中方法就是连接点 切入点 a) Service方法被增强就是切入点 通知 a) b) 引介 目标对象——代理目标对象 织入——指是代理新对象...
  • 目录动态代理JDK动态代理CGLIB动态代理AOP术语横切关注点切面通知目标代理连接点切入点织入通知类型基于注解小demo前置通知后置通知异常通知最终通知环绕通知定义公共切入点表达式切面优先级xml方式配置切面 ...
  • spring aop(三)--aop在spring的使用

    千次阅读 2014-12-23 16:39:20
    环绕通知在执行目标方法前后实施某种逻辑. d.异常抛出通知:在执行目标方法抛出异常实施某种逻辑. e.引入通知:在执行目标类添加新方法和属性. 一.先从一个前置通知例子入手: 1.ForumService.java和ForumServic
  • MyEclipse 6 Java 开发中文教程(完整版)

    热门讨论 2012-11-08 15:32:34
    10.4.3 开发环绕通知(Around Advice)AOP 应用 218 10.5 Spring数据库开发...... 222 MyEclipse 6 Java 开发中文教程 9 刘长炯著 10.5.1 DataSource 和 JDBCTemplate开发 222 10.5.2 Hibernate 整合 Spring开发.......

空空如也

空空如也

1 2 3 4
收藏数 74
精华内容 29
关键字:

java环绕通知的使用

java 订阅