标签:obj 需要 日志功能 aspect 不同的 返回 def for ini
AOP,面向切面编程是OOP之后出现的概念(大概)。
面向对象基本上就是针对类来设计代码,类中定义方法,逻辑中调用不同的类中不同的方法构成业务。
而面向切面中的切面到底是什么。在业务逻辑中,我们会分很多不同的模块,也有不同的类,而这些类的一些方法中,有一些共性功能。比如认证、日志、限流等功能,在各个模块都需要,那每一个功能可以被认为是一个切面。
类似一个三明治,面包、火腿、菜叶、番茄等等每一层都是一个功能模块,一刀切下去这个切面贯穿整个三明治各层,这一刀就形成一个切面,而这个切面就可以是比如日志功能。这是我的理解。
三个术语,不初步看一下后面看的时候就会一头雾水。
我们定义一个或多个切面(Aspect),切面中有各种需要执行的方法(Advice,如记录日志,认证请求),每个Advice又有一个pointcut定义这个Advice应该再什么地方执行。而当功能模块的某个方法,匹配到一个pointcut定义时,该pointcut对应的Advice就会介入执行,这就是一个joinpoint
。
对应AOP概念,Spring AOP主要做这几件事
和Spring Core中对bean的定义类似,也分为注解方式和配置文件方式(Spring里目前看到基本上所有相关功能都包含注解和配置文件两种配置方式)。
注解方式需要:
@Aspect
<aop:aspectj-autoproxy />
,这样Aspect才能找到对应的joinpoint配置方式好像不太是Spring推荐的方式了这里贴一个完整配置,其中定义了Aspect、pointcut表达式、Advice。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop/
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<!-- We don‘t need to this; This is required only in annotation based AOP support -->
<!-- <aop:aspectj-autoproxy /> -->
<aop:config>
<!-- Spring AOP Pointcut definitions -->
<aop:pointcut id="loggingOperation"
expression="execution(* com.howtodoinjava.demo.aop.EmployeeManager.*(..))" />
<aop:pointcut id="transactionOperation"
expression="execution(* com.howtodoinjava.demo.aop.EmployeeManager.getEmployeeById(..))" />
<!-- Spring AOP aspect 1 -->
<aop:aspect id="loggingAspect" ref="loggingAspectBean">
<!-- Spring AOP advises -->
<aop:before pointcut-ref="loggingOperation" method="logBefore" />
<aop:after pointcut-ref="loggingOperation" method="logAfter" />
</aop:aspect>
<!-- Spring AOP aspect 2 -->
<aop:aspect id="transactionAspect" ref="transactionAspectBean">
<aop:before pointcut-ref="transactionOperation" method="getEmployeeById" />
</aop:aspect>
</aop:config>
<!-- Spring AOP aspect instances -->
<bean id="loggingAspectBean" class="com.howtodoinjava.demo.aop.EmployeeCRUDLoggingAspect" />
<bean id="transactionAspectBean" class="com.howtodoinjava.demo.aop.EmployeeCRUDTransactionAspect" />
<!-- Target Object -->
<bean id="employeeManager" class="com.howtodoinjava.demo.aop.EmployeeManagerImpl" />
</beans>
一个简单的例子:
@Before("execution(* EmployeeManager.*(..))")
public void logBefore(JoinPoint joinPoint)
{
System.out.println("EmployeeCRUDAspect.logBeforeV2() : " + joinPoint.getSignature().getName());
}
logBefore方法就是一个Advice(要执行的动作),他是一个Before类型的Advice,会在pointcut指定位置之前执行。
这个Advice对应的pointcut就是("execution(* EmployeeManager.*(..))")
这句,标识匹配的方法时EmployeeManagerpacakge下的所有方法,方法参数和返回值都不限,匹配的是这个方法的执行。
Advice除了Before,还有After
- 执行后、Around
- 方法执行前后、 AfterReturn
- 方法正常结束、 AfterThrowing
- 方法抛出异常时执行时。
pointcut除了execution
也有多种表达式方式,比如匹配一个包中的所有方法within(packagename.xxx)
,匹配一个beanbean(beanNamexxx)
等。
只要是普通的bean即可,譬如@Component, @Controller等。在bean上不需要任何额外的定义,只要符合pointcut,相应的advice就会执行。
这也体现了Spring的涉及思路,非侵入式,减少依赖。
如果需要做日志,那么定义好Aspect就好,不需要动相应的组件代码
标签:obj 需要 日志功能 aspect 不同的 返回 def for ini
原文地址:https://www.cnblogs.com/mosakashaka/p/12609089.html