AOP的作用就是在基于OCP在不改变原有系统核心业务代码的基础上动态添加一些扩展功能。通常应用于日志的处理,事务处理,权限处理,缓存处理等等

首先,使用AOP需要添加的依赖有:spring-context、aspectjrt(AOP的实现依托于Aspect框架,版本最好不要使用1.8.5)、aspectjweaver。

SpringAOP的配置有xml和注解两种。其中基于注解的配置又有两种方式:

一、直接在xml文件中

<!-- 在spring-configs.xml中配置对类组件的扫描 -->

<context:component-scan

base-package="com.spring"/>

<!-- 启用AOP注解(自动为目标对象创建代理对象) -->

<aop:aspectj-autoproxy/>

在测试方法中用ClassPathXmlApplicationContext初始化容器对象

二、类中基于注解配置、即全注解形式

  @ComponentScan("com.spring.beans")

  @EnableAspectJAutoProxy

  public class AppConfig {

 }

在测试方法中用AnnotationConfigApplicationContext初始化容器对象

几个概念:

①、切面  具体类,使用@Aspect注解声明

②、连接点:JoinPoint 被拦截的方法

③、切入点:pointcut 拦截的内容,多个连接点集合

④、通知:即执行的动作,切面上某个特定连接点上执行的操作

功能增强 通知五种类型@Before、@AfterReturning、@AfterThrowing、@After以及@Around

它们的执行顺序和try-catch-finally相仿:

@Before前置通知,是 目标对象的业务方法执行之前执行

@AterReturning后置通知,是目标对象的业务方法正常结束才会执行,目标方法抛出异常则不执行,相当于try中的return

@AfterThrowing异常通知,是发生异常执行 发生异常才会执行相当于catch

@After最终通知,是无论有没有异常都会执行 相当于finally

@Around是其他四个通知的综合。

需要注意的是,如果发生异常,顺序是 Before--After---AfterThrowing。发生异常,顺序是:Before--After---AterReturning

  

常用AOP切点表达式有:

bean:匹配指定bean id的方法执行  @Before("bean(orderServiceImpl)") 因为该类已交spring管理,所以默认类名的首字母小写就是该类的bean

within 匹配 某包名下的类中的所有方法 如:@Before("within(com.beans.impl.*)" ) 包名+类名,就像在xml文件中定义bean的时候需要写的class属性

execution:细粒度方式 @Before("execution(* com.beans.impl.*.*(..) )") 即:(返回值类型 包名.类名.方法名(参数列表))

区别:bean和within只能指定到类,不能指定具体方法,而execution可以指定到哪一个类中的具体哪一个方法,更加灵活。

 其中使用的注解有:

接口的实现类用@Service注解

@Aspect标识其为一个AOP横切面对象

切入点@Ponitcut

@Order(数值),规定切面的执行顺序,如果是在xml配置,不依赖注解,在没有写order的情况下,两个切面如果对同一个方法,那么它的执行顺序跟配置文件中切面配置的先后顺序一致。

其中@Pointcut可以为通知的路径设置别名,代码入下:

@Pointcut("execution(* com.beans.impl.*.*(..))")
public void method(){}
@Before("method()")
public void fun(){
具体扩展的方法实体
}

  

AOP是如何为Bean对象创建代理对象的:cglib代理和jdk动态代理,概括的说,如果代理的是一个没有实现接口的目标对象,那么底层采用的是CGLIB代理,如果这个目标对象实现了某个接口那么底层就会采用JDK动态代理。其中CGLIB底层是代理对象继承了该目标对象,属于父子关系,而JDK动态代理的对象和目标对象实现同一个接口,类似兄弟关系。所以使用jdk代理的时候在getBean方法中,第二个参数 不能给一个实现类的.class,只能使用接口.class

输出日志

如果想要输出是哪个目标对象在调用哪个方法,可以使用JoinPoint作为日志输出,代码如下:

//权限管理
@Aspect
@Service
@Order(1)
public class permissionAspect{
private Logger logger = Logger.getLogger(Permission.Class.getName()); @Ponitcut("execution(* com.beans.impl.*.*(..))")
public void checkPermission(JoinPoint point) throws Throwable(){
//JointPoint是连接点对象,此对象中会封装目标对象以及目标方法相关信息,下面这句是:获取连接点所在类的名字
String clsName=point.getTarget().getClass().getName();
//getSignature()该方法是获取方法签名
String methodName=point.getSignature().getName(); //打印日志信息
logger.info("类名:"+clsName+“方法名:”+methodName+"权限监测")
}
}

  

最新文章

  1. EasyUI datagrid 日期时间格式化
  2. Finite State Machine 是什么?
  3. 白话Https
  4. 深入理解Java PriorityQueue
  5. Linux线程学习(二)
  6. jquery格式化时间戳 2011-01-01
  7. shell脚本调用spark-sql
  8. ResolverService跨子网的广播问题
  9. Android名词解释
  10. 推荐2一个在Java编码过程中得心应手的工具
  11. C#用DataTable实现Group by数据统计
  12. Socket编程实践(5) --TCP粘包问题与解决
  13. 数据分析与挖掘 - R语言:贝叶斯分类算法(案例三)
  14. CSS| 颜色名
  15. Js 面向对象之封装,继承,原型,原型链
  16. chorme快捷键
  17. Modelsim10.2c使用教程(一个完整工程的仿真)
  18. 父类与子类的转换as,is
  19. git+jenkins在windows机器上新建一个slave节点【转载】
  20. Android轻量级的开源缓存框架ASimpleCache

热门文章

  1. Linux c使用gumbo库解析页面表单信息(三)
  2. 关于SQLSERVER数据库连接池
  3. Ubuntu16.04下安装sublime text3
  4. Intellij Idea 解决字符乱码、设定颜色主题、字体
  5. PHP 轻量级 REST框架
  6. onmouseover与onmouseenter区别
  7. Centos 安装dhcp及简单配置
  8. python简单爬虫 用lxml解析页面中的表格
  9. &quot;HTML编码规范&quot; 笔记
  10. angular 的navigate 各种使用情况