美文网首页
Aop 面向切面的编程

Aop 面向切面的编程

作者: 我是邱邱 | 来源:发表于2018-09-09 15:45 被阅读0次

    实现Aop的方式有两种:

    1.xml配置文件方式

    首先写出目标类,目标类中有目标方法即切入点,例如

    @Repository
    public class Dao implements IDao{
    
        @Override
    //  切入点
        public void add() {
            // TODO Auto-generated method stub
            System.out.println("add info");
        }
    
        @Override
        public void delete() {
            // TODO Auto-generated method stub
            System.out.println("delete info");
        }
    
    }
    

    其次,需要有自己的切面类,切面类中包含关注点:例如

    // 切面类
    @Component
    public class LogAop {
        // 关注点
        // 参数 JoinPoint ,切入点对象,根据实际需求,可写可不写
        public void begin(JoinPoint jp){
            System.out.println("befor");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            // 方法名
            String name = jp.getSignature().getName();
            // 类名
            String cName = jp.getSignature().getDeclaringTypeName();
            //jp.getArgs();//获取方法的参数
            
            System.out.println("开始执行方法:" + cName + "." + name + ",执行时间:" + sdf.format(new Date()));
    //      System.out.println("执行时间:" + sdf.format(new Date()));
        }
        
        public void end(){
            System.out.println("after");
        }
        
        // 正常返回通知要执行的方法
        public void afterReturn(){
            System.out.println("after return");
        }
        
        // 环绕通知要执行的方法,必须要使用ProceedingJoinPoint 参数,表示切入点信息的对象
        public void around(ProceedingJoinPoint pjp){
            // 获取执行的方法的方法名
            System.out.println("around befor:" + pjp.getSignature().getName());
            try {
                // 执行目标方法
                pjp.proceed();
            } catch (Throwable e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("around after");
        }
        
    }
    

    再者,需要在bean.xml配置文件中配置引入切面类,配置如下:

    <!--扫描相关注解,即扫描例如@Component这些注解  -->
            <context:component-scan base-package="xmlaop"></context:component-scan> 
            
            <!--针对aop的配置  -->
            <aop:config>
                <!--配置切入点  ,配置切入点表达式 
                    execution(访问权限 包名.类名.方法名(参数));
                    第一个*表示所有的访问的权限
                    第二个*(..)表示的任意方法名,任意参数
                    本例子中,Dao类中所有的方法都是切入点
                -->
                <aop:pointcut expression="execution(* xmlaop.Dao.*(..))" id="pc"/>
                <!--配置切面类  ref:引入一个对象
                    method:前置通知要执行的方法
                    point-cut:切入点的引用
                 -->
                <aop:aspect ref="logAop">
                <!--前置通知  -->
                    <aop:before method="begin" pointcut-ref="pc"/>
                <!--后置通知  -->
                    <aop:after method="end" pointcut-ref="pc"/>
                <!--正常返回通知  -->
                    <aop:after-returning method="afterReturn" pointcut-ref="pc"/>
                <!--环绕通知  -->
                    <aop:around method="around" pointcut-ref="pc"/>
                </aop:aspect>
            </aop:config> 
    

    2.注解方式

    还可以直接在切面类上使用注解的方式配置切入点
    首先,还是先写目标对象,即目标对象中有目标方法即切入点

    @Component
    public class Dao implements IDao{
    
        @Override
        // 切入点
        public void add() {
            // TODO Auto-generated method stub
            System.out.println("add info");
        }
    
        @Override
        public void delete() {
            // TODO Auto-generated method stub
            System.out.println("delete info");
        }
    
    }
    

    其次,写出切面类,直接使用注解的方式在关注点上面配置切入点

    //动态扩展功能
    //切面类
    @Component
    //表示修饰的类是一个切面类
    @Aspect
    public class LogAop {
    //  如果所有的通知使用相同的切入点,就需要额外定义一个方法
        @Pointcut("execution(* annoaop.Dao.*(..))")//配置切入点
        public void pointcut() {
            
        }
    //关注点(通知,增强)
    //  参数可以不写,JoinPoint获取切入点接口对象,即可以获取执行的方法名
    //  @Before("execution(....)")
        @Before("pointcut()")//通过配置切入点的方法名来引用相关的切入点
        public void begin(JoinPoint joinPoint) {
            System.out.println("before");
    //      方法执行之前
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            
            String methodName = joinPoint.getSignature().getName();
            String className = joinPoint.getSignature().getDeclaringTypeName();
            
            String string = format.format(new Date());
            System.out.println(string + "开始执行;" + methodName + ";" + className);
        }
        
        @After("pointcut()")//后置通知
        public void end() {
            System.out.println("after");
        }
    //  正常返回通知执行的方法
        @AfterReturning("pointcut()")
        public void afterReturn() {
            System.out.println("after return");
        }
    //  环绕通知必须给参数,且必须使用ProceedingJoinPoint的参数,表示的是切入点信息
        @Around("pointcut()")
        public void around(ProceedingJoinPoint point) {
    //      获取执行方法的方法名
            System.out.println("around before" + point.getSignature().getName());
            try {
    //          执行目标方法
                point.proceed();
            } catch (Throwable e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("around after");
        }
    }
    
    

    再者,在配置文件中扫描相关的注解

    <!--扫描相关注解  只会扫描依赖注入以及控制反转的代码-->
            <context:component-scan base-package="annoaop"></context:component-scan> 
           
     <!--扫描aop的注解  -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    

    相关文章

      网友评论

          本文标题:Aop 面向切面的编程

          本文链接:https://www.haomeiwen.com/subject/lzfdgftx.html