精华内容
下载资源
问答
  • 在Spring AOP切面中启用新事务

    万次阅读 多人点赞 2019-07-31 19:16:01
    在工作中有一个在切面中需要记录一下操作日志的需求,而且要求这些操作日志要存入数据库,并且无论业务层有什么异常,日志照常记录,那就不能沿用业务层的事务,而是需要新启一个事务了。 sping的声明式事务就是靠...

    在工作中有一个在切面中需要记录一下操作日志的需求,而且要求这些操作日志要存入数据库,并且无论业务层有什么异常,日志照常记录,那就不能沿用业务层的事务,而是需要新启一个事务了。
    sping的声明式事务就是靠AOP来实现的,一般事务都在业务层中启用,那如果要在AOP的逻辑中启用一个新的事务要怎么做呢?比如下面的例子:

    //定义一个切点,这里指com.lidehang.remote包下所有的类的方法
    @Pointcut("execution(public * com.lidehang.remote..*.*(..))")
     public void remote(){}
    
    //切点指定的方法执行完返回后调用
    @AfterReturning(returning = "ret", pointcut = "remote()")
     public void doAfterReturning(JoinPoint joinPoint,Object ret) throws Throwable {
     	//一些切面逻辑,包含了数据库操作,为了即便业务层的原事务回滚也不会影响切面中的数据库操作,需要启用新的事务
    ...
     }
    

    经过我的测试,通过在doAfterReturning方法上加上注解@Transactional,并指定传播行为是REQUIRES_NEW依然不行。因为@Transactional也是声明式事务,本身就是AOP实现的,在AOP的代码中使用不起作用。所以就只能使用spring的编程式事务了,需要引入TransactionTemplate。如下:

    @Autowired
    private TransactionTemplate transactionTemplate;
    
    @AfterReturning(returning = "ret", pointcut = "remote()")
     public void doAfterReturning(JoinPoint joinPoint,Object ret) throws Throwable {
    //声明式事务在切面中不起作用,需使用编程式事务
    //设置传播行为:总是新启一个事务,如果存在原事务,就挂起原事务
    transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    transactionTemplate.execute(new TransactionCallback<T>() {
    @Override
    		public T doInTransaction(TransactionStatus arg0) {
     			//一些切面逻辑,包含了数据库操作
    ...
    }
    });
     }
    

    通过以上的步骤,切面里的逻辑会在新事务中执行,执行完就会提交,和业务层中的原事务无关,即便执行完切面逻辑后继续执行业务代码的过程中出现异常,业务层中的数据库操作因为有原事务而回滚,但切面中的数据库操作不会回滚,因为这是个新的事务!

    展开全文
  • aop切面插件包

    2017-07-15 10:19:49
    aop切面插件包
  • 主要介绍了Proxy实现AOP切面编程案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 最简单的aop切面方法

    2019-01-18 14:09:15
    最简单的aop切面方法,配置好后,自动扫描需要切面的方法,无需添加其他冗余代码。简洁实用@!@
  • 关于AOP切面的demo

    2018-02-24 10:35:03
    关于AOP切面的demo,研究aop的一些过程,使用aspecJ 。
  • 主要介绍了Spring AOP切面解决数据库读写分离实例详解的相关资料,需要的朋友可以参考下
  • AOPDemo:AOP切面demo-源码

    2021-05-09 19:58:18
    这是一个Android的AOP切面demo AOP是Aspect Oriented Programming的缩写,即『面向切面编程』。它和我们平时接触到的OOP都是编程的不同思想,OOP,即『面向对象编程』,它提倡的是将功能模块化,对象化,而AOP的思想...
  • 主要介绍了springboot配置aop切面日志打印过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • Spring的AOP切面编程

    千次阅读 2017-09-17 15:16:12
    Spring,AOP,切面,AOP切面

    语言苍白无力,我们直接代码说话

    package com.example.demo.aspect;
    import org.springframework.stereotype.Component;
    @Component
    public class AtithmeticCalulator {
    	
    	public int add(int a,int b){
    		return a+b;
    	}
    	
    	public int sub(int a,int b){
    		return a-b;
    	}
    	
    	public int mul(int a,int b){
    		return a*b;
    	}
    	
    	public int div(int a,int b){
    		return a/b;
    	}
    
    }
    
    这是一个类,以方法add为例,当我们想在每一个方面前面添加一个告诉自己方法名和参数的时候,你会怎么写?

    	public int add(int a,int b){
    		System.out.println("method mane:add    参数["+a+","+b+"]");
    		return a+b;
    	}
    	
    有没有感觉很麻烦,如果我四个方法都要用,你就要写4遍

    这个时候AOP派上用场

    package com.example.demo.aspect;  
      
    import java.util.Arrays;  
    import java.util.List;  
      
    import org.aspectj.lang.JoinPoint;  
    import org.aspectj.lang.annotation.After;  
    import org.aspectj.lang.annotation.Aspect;  
    import org.aspectj.lang.annotation.Before;  
    import org.springframework.stereotype.Component;  
      
    @Component//将组件加载到ioc容器,必须写,否则加载不到ioc容器  
    @Aspect//告诉ioc容器这是一个切面类,里面有切面方法  
    public class MyAspect {  
      
        //切面表达式public int com.example.demo.aspect.AtithmeticCalulator.*(int,int)  
        //包com.example.demo.aspect下的AtithmeticCalulator类所是public ,返回值是int,参数是(int,int)的方法  
        @Before("execution(public int com.example.demo.aspect.AtithmeticCalulator.*(int,int))")
        public void before(JoinPoint joinPoint) {  
            String name=joinPoint.getSignature().getName();  
            List<Object> args=Arrays.asList(joinPoint.getArgs());  
            System.out.println("----the method "+name +" is begin:"+args);  
        }  
          
          
        @After("execution(public int com.example.demo.aspect.AtithmeticCalulator.*(int,int))")  
        public void after(JoinPoint joinPoint) {  
            String name=joinPoint.getSignature().getName();  
            List<Object> args=Arrays.asList(joinPoint.getArgs());  
            System.out.println("----the method "+name +" is close:"+args);  
        }  
          
          
      
    }  


    运行结果所示:




    展开全文
  • AopDemo 一位大神些的高级 c# Aop切面的demo,让你方便了解和学会aop的精髓.
  • 本资源通过一个Category和Publisher表的实例,使用Spring框架实现AOP切面编程,其中实现了增删改查的功能,通过事物(tx)管理器、扫描业务逻辑、声明式事务达到切面编程效果。代码中有很详细的备注,适合新手入门
  • spring AOP 切面日志 分层打日志
  • Spring AOP 切面@Around注解的具体使用

    万次阅读 多人点赞 2019-02-19 23:21:36
    @Around注解可以用来在调用一个具体方法前和调用后来完成一些具体的任务。 比如我们想在执行controller...类似功能的注解还有@Before等等,用到了Spring AOP切面思想,Spring AOP常用于拦截器、事务、日志、权限验...

    @Around注解可以用来在调用一个具体方法前和调用后来完成一些具体的任务。

    比如我们想在执行controller中方法前打印出请求参数,并在方法执行结束后来打印出响应值,这个时候,我们就可以借助于@Around注解来实现;

    再比如我们想在执行方法时动态修改参数值等

    类似功能的注解还有@Before等等,用到了Spring AOP切面思想,Spring AOP常用于拦截器、事务、日志、权限验证等方面。

    完整演示代码如下:

    需要说明的是,在以下例子中,我们即可以只用@Around注解,并设置条件,见方法run1();也可以用@Pointcut和@Around联合注解,见方法pointCut2()和run2(),这2种用法是等价的。如果我们还想利用其进行参数的修改,则调用时必须用joinPoint.proceed(Object[] args)方法,将修改后的参数进行回传。如果用joinPoint.proceed()方法,则修改后的参数并不会真正被使用。

    import org.aspectj.lang.ProceedingJoinPoint;
    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.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import javax.persistence.EntityManager;
    
    /**
     * 控制器切面
     *
     * @author lichuang
     */
    
    @Component
    @Aspect
    public class ControllerAspect {
    
        private static final Logger logger = LoggerFactory.getLogger(ControllerAspect.class);
    
        @Autowired
        private EntityManager entityManager;
    
        /**
         * 调用controller包下的任意类的任意方法时均会调用此方法
         */
        @Around("execution(* com.company.controller.*.*(..))")
        public Object run1(ProceedingJoinPoint joinPoint) throws Throwable {
            //获取方法参数值数组
            Object[] args = joinPoint.getArgs();
            //得到其方法签名
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            //获取方法参数类型数组
            Class[] paramTypeArray = methodSignature.getParameterTypes();
            if (EntityManager.class.isAssignableFrom(paramTypeArray[paramTypeArray.length - 1])) {
                //如果方法的参数列表最后一个参数是entityManager类型,则给其赋值
                args[args.length - 1] = entityManager;
            }
            logger.info("请求参数为{}",args);
            //动态修改其参数
            //注意,如果调用joinPoint.proceed()方法,则修改的参数值不会生效,必须调用joinPoint.proceed(Object[] args)
            Object result = joinPoint.proceed(args);
            logger.info("响应结果为{}",result);
            //如果这里不返回result,则目标对象实际返回值会被置为null
            return result;
        }
    
        @Pointcut("execution(* com.company.controller.*.*(..))")
        public void pointCut2() {}
    
        @Around("pointCut2()")
        public Object run2(ProceedingJoinPoint joinPoint) throws Throwable {
            //获取方法参数值数组
            Object[] args = joinPoint.getArgs();
            //得到其方法签名
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            //获取方法参数类型数组
            Class[] paramTypeArray = methodSignature.getParameterTypes();
            if (EntityManager.class.isAssignableFrom(paramTypeArray[paramTypeArray.length - 1])) {
                //如果方法的参数列表最后一个参数是entityManager类型,则给其赋值
                args[args.length - 1] = entityManager;
            }
            logger.info("请求参数为{}",args);
            //动态修改其参数
            //注意,如果调用joinPoint.proceed()方法,则修改的参数值不会生效,必须调用joinPoint.proceed(Object[] args)
            Object result = joinPoint.proceed(args);
            logger.info("响应结果为{}",result);
            //如果这里不返回result,则目标对象实际返回值会被置为null
            return result;
        }
    }

     

    展开全文
  • JAVA简单AOP切面编程;依赖注入;代码配置Bean源码 JAVA简单AOP切面编程;依赖注入;代码配置Bean源码
  • spring aop切面拦截指定类和方法实现流程日志跟踪 一般情况下,在不侵入业务代码的情况下,需要做流程日志跟踪是比较合理的 采用springaop切面思想
  • spring AOP切面编程

    2015-02-06 22:24:38
    spring AOP切面编程 运行环境:eclipse 构建工具:maven 不提供maven构建,maven用来解决jar包的依赖
  • Spring自定义AOP切面

    千次阅读 2021-03-23 19:38:38
    切面 切面需要实现PointcutAdvisor接口,包含切点和通知。 package com.morris.spring.aop; import org.aopalliance.aop.Advice; import org.springframework.aop.Pointcut; import org.springframework.aop....

    切面

    切面需要实现PointcutAdvisor接口,包含切点和通知。

    package com.morris.spring.aop;
    
    import org.aopalliance.aop.Advice;
    import org.springframework.aop.Pointcut;
    import org.springframework.aop.support.AbstractPointcutAdvisor;
    
    @SuppressWarnings("serial")
    public class UserServiceAdvisor extends AbstractPointcutAdvisor {
    
    	@Override
    	public Advice getAdvice() {
    		return new UserServiceAdvice();
    	}
    
    	@Override
    	public Pointcut getPointcut() {
    		return new UserServicePointcut();
    	}
    }
    

    切点

    切点需要实现Pointcut,里面要实现对类的匹配和方法的匹配。

    这里不对类进行校验,所以使用Spring内部的ClassFilter.TRUE。

    对方法的匹配需要实现MethodMatcher,所以UserServicePointcut同时实现了MethodMatcher和Pointcut。

    package com.morris.spring.aop;
    
    import com.morris.spring.annotation.Abcd;
    import org.springframework.aop.ClassFilter;
    import org.springframework.aop.MethodMatcher;
    import org.springframework.aop.Pointcut;
    import org.springframework.aop.support.AopUtils;
    
    import java.lang.reflect.Method;
    
    public class UserServicePointcut implements MethodMatcher, Pointcut {
    	@Override
    	public boolean matches(Method method, Class<?> targetClass) {
    		if(method.getName().equals("query")) {
    			return true;
    		}
    		return false;
    	}
    
    	@Override
    	public boolean isRuntime() {
    		return false;
    	}
    
    	@Override
    	public boolean matches(Method method, Class<?> targetClass, Object... args) {
    		return false;
    	}
    
    	@Override
    	public ClassFilter getClassFilter() {
    		return ClassFilter.TRUE;
    	}
    
    	@Override
    	public MethodMatcher getMethodMatcher() {
    		return this;
    	}
    }
    

    通知

    通知主要是对目标方法的增强,这里只是打印。

    package com.morris.spring.aop;
    
    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    
    public class UserServiceAdvice implements MethodInterceptor {
    
    	@Override
    	public Object invoke(MethodInvocation invocation) throws Throwable {
    		System.out.println(invocation.getMethod().getName()+"-------------------------");
    		return invocation.proceed();
    	}
    }
    

    测试类

    package com.morris.spring.demo.annotation;
    
    import com.morris.spring.aop.UserServiceAdvisor;
    import com.morris.spring.service.UserService;
    import com.morris.spring.service.UserServiceImpl;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    
    @Configuration
    @EnableAspectJAutoProxy // 开启AOP
    public class CustomerAspectDemo {
    
    	public static void main(String[] args) {
    		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
    		applicationContext.register(UserServiceImpl.class);
    		applicationContext.register(UserServiceAdvisor.class); // 自定义切面
    		applicationContext.register(CustomerAspectDemo.class); // 开启AOP
    		applicationContext.refresh();
    		UserService userService = applicationContext.getBean(UserService.class);
    		userService.query("hello");
    	}
    }
    

    运行结果如下:

    query-------------------------
    UserServiceImpl hello
    

    发现通知中的增强代码执行了。

    尝试获得目标方法上的注解信息

    UserServiceImpl.query()方法上面加上@Abcd(“abcd”)
    注解:

    public class UserServiceImpl implements UserService {
    
    	@Abcd("abcd")
    	@Override
    	public void query(String name) {
    		System.out.println("UserServiceImpl " + name);
    	}
    }
    

    com.morris.spring.aop.UserServicePointcut#matches(java.lang.reflect.Method, java.lang.Class<?>)

    public boolean matches(Method method, Class<?> targetClass) {
    	if(method.isAnnotationPresent(Abcd.class)) {
    		return true;
    	}
    	return false;
    }
    

    运行结果会发现通知中的增强代码并没有被执行,这是为什么呢?目标方法query()上面明明有@Abcd注解,为什么获取不到呢?

    在matches()方法中打上断点,会发现这个方法会被调用两次,第一次会返回true,第二次返回false,为什么两次结果会不一样呢?

    先来看一下这两次调用的调用时机:

    1. 第一次调用时,匹配方法,如果匹配上了就会生成代理对象,Method所在的类为com.morris.spring.service.UserServiceImpl。

    2. 第二次调用时,调用代理对象的方法时会再次匹配,因为有的方法不需要代理,Method所在的类为com.morris.spring.service.UserService。

    第二次调用时Method是来自于UserService接口,而接口上面的方法是没有注解的,这点也可以从动态代理生成的类中看出:

    static {
    	try {
    	    m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
    		// 来自接口
    	    m3 = Class.forName("com.morris.spring.service.UserService").getMethod("query", Class.forName("java.lang.String"));
    	    m4 = Class.forName("com.morris.spring.service.UserService").getMethod("hi", Class.forName("com.morris.spring.entity.D"));
    	    m2 = Class.forName("java.lang.Object").getMethod("toString");
    	    m0 = Class.forName("java.lang.Object").getMethod("hashCode");
    	} catch (NoSuchMethodException var2) {
    	    throw new NoSuchMethodError(var2.getMessage());
    	} catch (ClassNotFoundException var3) {
    	    throw new NoClassDefFoundError(var3.getMessage());
    	}
    }
    

    而UserService.query()方法上面并没有@Abcd注解,那么要怎么样才能获得注解的信息呢?Spring提供了下面的工具类:

    Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
    if(specificMethod.isAnnotationPresent(Abcd.class)) {
    	return true;
    }
    

    方法参数级别更细粒度的匹配

    MethodMatcher还有两个方法:

    boolean isRuntime();
    boolean matches(Method method, Class<?> targetClass, Object... args);
    

    这两个方法配合使用能在运行时对参数的值进行匹配。

    public boolean isRuntime() {
    	return true;
    }
    
    public boolean matches(Method method, Class<?> targetClass, Object... args) {
    	if(null != args && null != args[0] && "morris".equals(args[0])) {
    		System.out.println("matches  args");
    		return true;
    	}
    	return false;
    }
    

    需要满足两个条件这个带方法参数的matches()才会执行(这个方法只会执行一次,真正调用时才会知道参数的具体值):

    1. 不带方法参数的matches()返回true。

    2. isRuntime()返回true。

    展开全文
  • spring aop 切面添加日志

    千次阅读 2018-06-22 16:43:27
    这是一个非常简单的spring aop切面添加日志的程序,下面来看一下这个程序1、程序使用jar包2、切面类LoggingAspect.javapackage com.cailei.aop.aspect; import java.util.Arrays; import org.aspectj.lang....
  • 主要介绍了解决springboot的aop切面不起作用问题(失效的排查),具有很好的参考价值,希望对大家有所帮助。 一起跟随小编过来看看吧
  • AOP切面的实践 下面是一个在spring mvc中关于切面如何使用的例子,可以指直观的理解切面到底有什么作用 1、引用 AspectJ jar 包依赖 pom.xml 文件添加依赖 org.aspectj aspectjrt 1.9.2 2、创建两个新的包 ...
  • Spring mvc mybatis plus 实现AOP 切面日志系统,带有数据库。可以自行拓展
  • spring xml 实现aop切面编程 内附注释,希望对入门的新手有帮助
  • JavaEE JDK动态代理实现AOP切面功能
  • Spring 动态代理和aop切面编程例子,自己写的例子!!!!!!!
  • 二、Spring AOP 切面的定义

    千次阅读 2018-11-06 13:05:26
    Spring AOP 切面的定义 Spring AOP定义切面有多种方式,例如 1、使用@AspectJ注解 2、使用&lt;aop:aspect&gt;标签 3、使用&lt;aop:advisor&gt;标签 4、使用Advisor类   一、使用@AspectJ...
  • Spring AOP切面声明方式

    2019-08-10 09:54:37
    Spring AOP切面声明方式有注解和xml方式。 第一种:在XML中声明切面 AOP配置元素 用 途 <aop:advisor> 定义AOP通知器 <aop:after> 定义AOP后置通知(不管被通知的方法是否执行成功) <aop:...
  • springboot+AOP切面监控接口调用详情

    千次阅读 2020-05-21 10:49:40
    springboot+AOP切面监控接口调用详情
  • Aop切面自定义注解的使用

    千次阅读 2020-12-16 14:42:27
    本文主要记录如何使用aop切面的方式来实现日志记录功能。 主要记录的信息有: 操作人,方法名,参数,运行时间,操作类型(增删改查),详细描述,返回值。 二:项目结构图 三:代码实现 1.配置文件 spring.aop.auto=...
  • AOP切面编程两种实现方式公共jar包2.方式一:配置bean切入2.1创建日志切面类2.2 配置日志切面类方式二 注解模式实现1.开启注解扫描2. 只配置日志切面类 两种实现方式 公共jar包 <!-- ...
  • spring aop 切面测试

    千次阅读 2017-01-21 11:18:08
    spring 配置 aop 切面类 package com.changhang.urgoo.impl.utils; import org.aspectj.

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 123,940
精华内容 49,576
关键字:

aop切面