AOP的应用

Spring-AOP 是对 AOP框架之一。其他比如还有AspectJ

Aspect-Oriented-Programming(面向切面编程),一种编程思想。

切面:Aspect,由切入点额外功能(增强)组成。

作用:提供了新的编程角度,不再只是考虑类、对象,而可以考虑切面。切面和目标形成 代理,解决项目业务中额外功 能冗余的问题。

1、为什么会有Aop(面向切面编程)的思想?
业务层存在问题,业务层的组成为核心代码+额外功能,从而存在这大量的代码重复,增加了代码的冗余,是项目维护存在了极大隐患。从而出现了两种代理
(1)静态代理
另外写一个类继承与核心代码相同的接口,在内部新建一个核心代码部分,在内部进行修饰(个人感觉与装饰者模式差不多)。

    UserService us=new UserServiceImpl();
    public void updateUser(User user){
        System.out.println("事务管理功能"); //代理类负责额外功能
        us.updateUser(user); // 目标自己负责核心功能
    }
    public void inserUser(User user){ 
        System.out.println("事务管理功能");//代理类负责额外功能
        us.insertUser(user);// 目标自己负责核心功能
    }
    public User queryUser(Integer id){ 
        System.out.println("事务管理功能");//代理类负责额外功能
        us.queryUser(user);// 目标自己负责核心功能
    }

(2)动态代理
动态代理分为两种
1、jdk代理要求代理类和核心类实现了相同的接口。
2、cglib动态代理( 第三方cglib库中的一套api ) 通过继承目标保证功能一致
Spring中的aop章节底部采用了这两种代理的方式实现,并对动态代理提供了简单的、可操作性强的决绝方案。

Aop代码流程

1、在pom.xml中添加依赖

    org.springframework
    spring-context-support
    4.3.6.RELEASE


    org.springframework
    spring-aspects
    4.3.6.RELEASE




简单举个例子

1、创建target

    @Override
    public Integer InsertUser(User user) {
        System.out.println("核心功能");
        return 4;
    }

    @Override
    public User findQueryOne(Integer id) {
        System.out.println("核心功能");
        return new User();
    }
}

2、创建advice
这里有五种
1、MethodBeforeAdvice在核心代码运行之前运行

    //method 当前执行的方法对象
    //args方法的参数
    //target 目标对象
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(new Date().toLocaleString()+" "+method.getName()+"被访问");
    }
}
简单打印日志文件

2、AfterReturningAdvice 在核心代码之后运行

    //returnValue核心业务返回值
    //Method方法对象
    //args方法的参数表
    //target目标对象
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("return value = "+returnValue);
        System.out.println("method = "+method.getName());
    }
}

3、MethodInterceptor 在核心代码之间环绕(前后都执行,如果仅仅是之前或者之后,尽量不要用这个替代前两者,这点Spring官方明确规定)

    /*环绕
    * MethodInvocation
    * */
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("Interceptor1");

        Object proceed = invocation.proceed();//执行目标的核心功能
        System.out.println("Interceptor2");
        return proceed;//业务结果向上返回
    }
}

4、ThrowsAdvice异常额外功能(了解)

    //目标业务方法中抛出异常时,执行此方法。ex=抛出的异常对象
    public void afterThrowing(Exception ex){
        System.out.println(ex.getMessage()+"~~~");
    }
}

5、AfterAdvice(了解)与AfterRetuenAdvice用法相似

3、配置切入点(编织)

 
 


       

1、切入点表达式
(1)execution

1> * com.service.UserServiceImpl.queryUser(..)
    修饰符:任意
    返回值:任意
    包:com.service
    类:UserServiceImpl
    方法:queryUser
    参数表:任意
2> * com.service.UserServiceImpl.*(..)
    修饰符:任意
    返回值:任意
    包:com.service
    类:UserServiceImpl
    方法:所有,任意
    参数表:任意
3> * com..UserServiceImpl.*(..)
    修饰符:任意
    返回值:任意
    包:com包,及其子包
    类:UserServiceImpl
    方法:所有,任意
    参数表:任意
4> * com.service.*.*(..)
    修饰符:任意
    返回值:任意
    包:com.service
    类:所有,任意
    方法:所有,任意
    参数表:任意
5> * *(..)    不建议
    修饰符:任意
    返回值:任意
    包:任意
    类:所有,任意
    方法:所有,任意
    参数表:任意
6> * com.service.UserServiceImpl.query*(..)  【技巧:批量切入】
    修饰符:任意
    返回值:任意
    包:com.service
    类:UserServiceImpl
    方法:所有,任意
    参数表:任意
  *注意:尽量精确,避免不必要的切入

注意:

切入点表达式只会拦截在配置文件中配置的类型对象。
2、within(描述 包、类、以及类下所有方法的切入)
within(包)
within(类)
3、orgs(符合方法插入、描述符合该参数的所有方法)
args(int,String,com.entity.User) 参数表如此的方法

当然参数之间可以联用(and 、not、or

用法和基本用法相同。
测试类:

    @Override
    public Integer InsertUser(User user) {
        System.out.println("核心功能");
        return 4;
    }

    @Override
    public User findQueryOne(Integer id) {
        System.out.println("核心功能");
        return new User();
    }
}

@Test

    public void test1(){
     ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
     UserService userservice1 = classPathXmlApplicationContext.getBean("userservice", UserService.class);
        userservice1.InsertUser(new User());
        userservice1.findQueryOne(1);
 }
}

测试结果:AOP的应用_第1张图片

你可能感兴趣的:(AOP的应用)