最新公告
  • 欢迎您光临极客文库,登录获取更多编程学习资源及文章!立即加入我们
  • 基于AspectJ的AOP开发之注解开发方式(二)

    入门案例

    为目标类,定义切面类

    打开IDEA,新建一个demo1,创建一个ProductDao,写上几个具体的方法用于测试。

    package com.jikewenku.aspectJ.demo1;
    
    public class ProductDao {
    
        public void save(){
            System.out.println("保存商品...");
        }
    
        public void update(){
            System.out.println("修改商品...");
        }
    
        public void delete(){
            System.out.println("删除商品...");
        }
    
        public void findOne(){
            System.out.println("查询一个商品...");
        }
    
        public void findAll(){
            System.out.println("查询所有商品...");
        }
    
    }
    

    这就是我们定义的目标类,接下来我们要去完成配置

    
    
    
        
        
    
        
        
    
        
        
    
    

    在相同的包下新建一个类MyAspectAnno

    package com.jikewenku.aspectJ.demo1;
    
    import org.aspectj.lang.annotation.*;
    
    /**
     * 切面类
     */
    @Aspect
    public class MyAspectAnno {
    
        @Before(value="execution(* com.jikewenku.aspectJ.demo1.ProductDao.*(..))")
        public void before(){
            System.out.println("前置通知==================");
        }
    }
    

    新建一个测试类SpringDemo1

    package com.jikewenku.aspectJ.demo1;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import javax.annotation.Resource;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class SpringDemo1 {
    
        @Resource(name="productDao")
        private ProductDao productDao;
    
        @Test
        public void demo1(){
            productDao.save();
            productDao.update();
            productDao.delete();
            productDao.findAll();
            productDao.findOne();
        }
    
    }
    

    运行程序

    如图每一个方法之前都进行了前置增强,如果只想对某个方法前置增强,只需要该表达式就可以了。

    @Before前置通知

    前置通知就是在方法执行之前进行增强,可以在方法中传入JoinPoint对象,用来获得切点信息

    打开MyAspectAnno,修改方法如下,只对save进行前置增强

    @Before(value="execution(* com.jikewenku.aspectJ.demo1.ProductDao.save(..))")
    public void before(JoinPoint joinPoint){
        System.out.println("前置通知=================="+joinPoint);
    }
    

    运行程序,在保存之前进行了前置增强,并输出了切点信息

    @AfterReturning 后置通知

    打开MyAspectAnno,修改方法如下

    @AfterReturning(value="execution(* com.jikewenku.aspectJ.demo1.ProductDao.uodate(..))")
    public void afterReturing(){
        System.out.println("后置通知==================");
    }
    

    在修改方法执行之后输出了后置通知

    通过returning属性,可以定义方法返回值,作为参数

    修改ProductDao中的方法

    public String update(){
        System.out.println("修改商品...");
        return "hello";
    }
    

    后置通知中获得返回的内容

    @AfterReturning(value="execution(* com.jikewenku.aspectJ.demo1.ProductDao.uodate(..))",returning = rusult)
    public void afterReturing(Object result){
        System.out.println("后置通知=================="+result);
    }
    

    运行程序,修改商品执行之后的后置通知拿到了返回值

    @Around 环绕通知

    around方法的返回值就是目标代理方法执行返回值

    参数为ProceedingJoinPoint可以调用拦截目标方法执行

    重点:如果不调用ProceedingJoinPoint的proceed方法,那么目标方法就被拦截了。

    @Around(value="execution(* com.jikewenku.aspectJ.demo1.ProductDao.delete(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前通知================");
        Object obj = joinPoint.proceed(); // 执行目标方法
        System.out.println("环绕后通知================");
        return obj;
    }
    

    测试一下

    删除方法前后都有环绕通知了

    @AfterThrowing 异常抛出通知

    @AfterThrowing(value="execution(* com.jikewenku.aspectJ.demo1.ProductDao.findOne(..))")
    public void afterThrowing(){
        System.out.println("异常抛出通知==============");
    }
    

    运行程序,进行单元测试,此时findOne是没有异常的,所以没有异常通知

    接下来我们制造一个异常,ProductDao中修改

    public void findOne(){
            System.out.println("查询一个商品...");
            int i = 1/0;
        }
    

    运行程序,异常抛出通知成功输出

    通过设置throwing属性,可以设置发生异常对象参数

    @AfterThrowing(value="execution(* com.jikewenku.aspectJ.demo1.ProductDao.findOne(..))".Throwing="e")
    public void afterThrowing(Throwable e){
        System.out.println("异常抛出通知=============="+e.getMessage());
    }
    

    运行程序。打印了异常信息。

    @After 最终通知

    无论是否出现异常,最终通知总是会被执行

    @After(value="execution(* com.jikewenku.aspectJ.demo1.ProductDao.findAll(..))")
    public void after(){
        System.out.println("最终通知==================");
    }
    

    运行程序,在findAll方法执行后就会执行最终通知,如果产生异常也会执行,这里就不演示了。

    通过@Pointcut为切点命名

    在每个通知内定义其诶单,会造成工作量大,不易维护,对于重复的切点,可以使用@Pointcut进行定义

    切点方法:private void 无参数方法,方法名为切点名

    当通知多个切点时,可以使用||进行连接

    package com.jikewenku.aspectJ.demo1;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    
    /**
     * 切面类
     */
    @Aspect
    public class MyAspectAnno {
    
        @Before(value="myPointcut1()")
        public void before(JoinPoint joinPoint){
            System.out.println("前置通知=================="+joinPoint);
        }
    
        @AfterReturning(value="myPointcut2()",returning = "result")
        public void afterReturing(Object result){
            System.out.println("后置通知=================="+result);
        }
    
        @Around(value="myPointcut3()")
        public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("环绕前通知================");
            Object obj = joinPoint.proceed(); // 执行目标方法
            System.out.println("环绕后通知================");
            return obj;
        }
    
        @AfterThrowing(value="myPointcut4()",throwing = "e")
        public void afterThrowing(Throwable e){
            System.out.println("异常抛出通知=============="+e.getMessage());
        }
    
        @After(value="myPointcut5()")
        public void after(){
            System.out.println("最终通知==================");
        }
    
    
        @Pointcut(value="execution(* ProductDao.save(..))")
        private void myPointcut1(){}
    
        @Pointcut(value="execution(* ProductDao.update(..))")
        private void myPointcut2(){}
    
        @Pointcut(value="execution(* ProductDao.delete(..))")
        private void myPointcut3(){}
    
        @Pointcut(value="execution(* ProductDao.findOne(..))")
        private void myPointcut4(){}
    
        @Pointcut(value="execution(* ProductDao.findAll(..))")
        private void myPointcut5(){}
    }
    

    运行程序,效果是一样的,维护起来也更加方便

    本站所有文章均由网友分享,仅用于参考学习用,请勿直接转载,如有侵权,请联系网站客服删除相关文章。若由于商用引起版权纠纷,一切责任均由使用者承担
    极客文库 » 基于AspectJ的AOP开发之注解开发方式(二)

    常见问题FAQ

    如果资源链接失效了怎么办?
    本站用户分享的所有资源都有自动备份机制,如果资源链接失效,请联系本站客服QQ:2580505920更新资源地址。
    如果用户分享的资源与描述不符怎么办?
    可以联系客服QQ:2580505920,如果要求合理可以安排退款或者退赞助积分。
    如何分享个人资源获取赞助积分或其他奖励?
    本站用户可以分享自己的资源,但是必须保证资源没有侵权行为。点击个人中心,根据操作填写并上传即可。资源所获收益完全归属上传者,每周可申请提现一次。
    如果您发现了本资源有侵权行为怎么办?
    及时联系客服QQ:2580505920,核实予以删除。

    参与讨论

    • 108会员总数(位)
    • 3700资源总数(个)
    • 5本周发布(个)
    • 2 今日发布(个)
    • 202稳定运行(天)

    欢迎加入「极客文库」,成为原创作者从这里开始!

    立即加入 了解更多
    成为赞助用户享有更多特权立即升级