【Spring】AOP - 面向切面
面向切面 - AOP
切面实现了横切关注点(跨越多个应用对象的逻辑)的模块化:
术语
通知(Advice)
在AOP术语中,切面的工作被成为通知。通知定义了切面是什么以及何时使用。
Spring切面可以应用5中类型的通知:
- Before —— 在方法被调用之前调用通知;
- After —— 在方法完成之后调用通知,无论方法执行是否成功;
- After-returning —— 在方法成功执行之后调用通知;
- After-throwing —— 在方法抛出异常后调用通知;
- Around —— 通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为;
连接点(Joinpoint)
连接点是在应用执行过程中能够插入切面的一个点。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。
切点(Pointcut)
切点的定义会匹配通知所要织入的一个或多个连接点。通常使用明确的类和方法名称来指定这些切点,或是利用正则表达式定义匹配的类和方法名称模式来指定这些切点。
切点用于准确定位应该在什么地方应用切面的通知。
切面(Aspect)
切面是通知和切点的结合。通知和切点共同定义了关于切面的全部内容——它是什么,在何时和何处完成其他功能。
引入(Introduction)
引入允许我们向现有的类添加新方法或属性,通过通知类,从而可以在无需修改现有的类的情况下,让它们具有新的行为和状态。
参见<aop:declare-parents>元素的使用,引入新的接口行为。
织入(Weaving)
织入是将切面应用到目标对象来创建新的代理对象的过程,切面在指定的连接点被织入到目标对象中(注入前置、后置通知等)。
在目标对象的生命周期里有多个点可以进行织入:
- 编译期—— 切面在目标类编译期被织入,这种方式需要特殊的编译器,如AspectJ;
- 类加载期—— 切面在目标类家在到JVM时被织入,这种方式需要特殊的类加载器(ClassLoader);
- 运行期—— 切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代理对象。Spring AOP就是以这种方式织入切面的;
Spring对AOP的支持
Spring提供了4中各具特色的AOP支持:
- 基于代理的经典AOP;
- @AspectJ注解驱动的切面;
- 纯POJO切面;
- 注入式AspectJ切面;
Spring通知是Java编写 —— Spring所创建的通知都是用标准的Java类编写的;
Spring在运行期通知对象 —— Spring运行时才创建代理对象,所以我们不需要特殊的编译器来织入Spring AOP的切面;
Spring只支持方法连接点 —— Spring基于动态代理,所以Spring只支持方法连接点,不支持构造器和字段连接点;
SpringAOP 之 定义切点
Spring AOP中,需要使用AspectJ的切点表达式语言来定义切点。
Spring AOP支持的AspectJ切点指示符
Spring仅支持AspectJ切点指示器的一个子集:
AspectJ指示器 | 描述 |
execution | 用于匹配方法执行的连接点 |
within | 用于匹配指定类型内的方法执行 |
this | 用于匹配当前AOP代理对象类型的执行方法,注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配 |
target | 用于匹配当前目标对象类型的执行方法,注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配 |
args | 用于匹配当前执行的方法传入的参数为指定类型的执行方法 |
@within | 用于匹配持有指定注解类型内的方法 |
@target | 用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解 |
@args | 用于匹配当前执行的方法传入的参数持有指定注解的执行 |
@annotation | 用于匹配当前执行方法持有指定注解的方法 |
bean | Spring AOP扩展的,用于匹配特定名称的Bean对象的执行方法 |
reference pointcut | 表示引用其他命名切入点 |
在Spring中尝试使用其他AspectJ指示器时,将会抛出IllegalArgumentException异常。
http://sishuok.com/forum/posts/list/281.html
SpringAOP 之 基于POJO切面
在XML中声明切面
Spring提供了声明式切面的选择。
Spring的AOP配置元素简化了基于POJO切面的声明:
AOP配置元素 | 功能 |
---|---|
<aop:advisor> | 定义一个AOP通知器 |
<aop:after> | 定义一个AOP后置通知(不考虑被通知的方法是否执行成功) |
<aop:after-returning> | 定义一个AOP返回后通知 |
<aop:after-throwing> | 定义一个AOP抛出后通知 |
<aop:around> | 定义一个AOP环绕通知 |
<aop:aspect> | 定义一个切面 |
<aop:before> | 定义一个AOP前置通知 |
<aop:config> | 顶层的AOP元素。大多数<aop:*>元素必须包含在<aop:config>里 |
<aop:pointcut> | 定义一个切点 |
<aop:declare-parents> | 为被通知的对象引入额外的接口,并透明地实现 |
声明前置和后置通知
XML Bean配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsd"><!-- Root Context: defines shared resources visible to all other web components --><bean id="advised" class="com.springtest.AdvisedObj" /><bean id="advising" class="com.springtest.AdvisingObj" /><aop:config><aop:aspect ref="advising"><aop:pointcut id="performance" expression="execution(* com.springtest.AdvisedObj.perform(..))" /><aop:before pointcut-ref="performance" method="beforeExecute" /><aop:after pointcut-ref="performance" method="afterExecute" /> </aop:aspect></aop:config></beans>
Java Code:
package com.springtest;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.springtest.AdvisedObj;
import com.springtest.AdvisingObj;public class SpringCoreTest{public static void main(String[] args){ApplicationContext ctx = new FileSystemXmlApplicationContext("//Users/... .../beans_config.xml");AdvisedObj advisedObj = (AdvisedObj)ctx.getBean("advised");advisedObj.perform();}
}
package com.springtest;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class AdvisedObj {private static final Logger logger = LoggerFactory.getLogger(AdvisedObj.class);public void perform(){logger.info("AdvisedObj perform().");}
}
package com.springtest;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class AdvisingObj {private static final Logger logger = LoggerFactory.getLogger(AdvisingObj.class);public void beforeExecute(){logger.info("AdvisingObj beforeExcecute().");}public void afterExecute(){logger.info("AdvisingObj afterExecute().");}
}
执行结果:
00:52:24.350 [main] INFO com.springtest.AdvisingObj - AdvisingObj beforeExcecute().
00:52:24.367 [main] INFO com.springtest.AdvisedObj - AdvisedObj perform().
00:52:24.367 [main] INFO com.springtest.AdvisingObj - AdvisingObj afterExecute().
关于Spring AOP配置元素,大多数的AOP配置元素必须在<aop:config>元素的上下文内使用。
在所有的通知元素中,pointcut属性定义了通知所应用的切点。pointcut属性的值是使用AspectJ切点表达式语法所定义的切点。
<aop:pointcut>元素所定义的切点可以被同一个<aop:aspect>元素内的所有通知元素所引用。如果想让定义的切点能够在多个切面使用,可以把<aop:pointcut>元素放在<aop:config>元素的作用域内。
声明环绕通知
使用<aop:round>元素。使用环绕通知,可以完成之前前置通知和后置通知所实现的相同功能,但是只需要在一个方法中实现。
参考下面新的通知方法,它使用了ProceedingJoinPoint作为方法的参数。这个对象能让我们在通知里调用被通知方法。通知方法可以完成任何它所需要做的事情,如果希望把控制转给被通知的方法时,可以调用ProceedingJoinPoint的proceed方法。
必须调用proceed方法,如果忘记,通知将会阻止被通知的方法的调用。还可以在通知里多次调用被通知的方法。
示例:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsd"><!-- Root Context: defines shared resources visible to all other web components --><bean id="advised" class="com.springtest.AdvisedObj" /><bean id="advising" class="com.springtest.AdvisingObj" /><aop:config><aop:aspect ref="advising"><aop:pointcut id="performance" expression="execution(* com.springtest.AdvisedObj.perform(..))" /><!-- <aop:before pointcut-ref="performance" method="beforeExecute" /><aop:after pointcut-ref="performance" method="afterExecute" /> --> <aop:around pointcut-ref="performance" method="roundExecute" /></aop:aspect></aop:config></beans>
package com.springtest;import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class AdvisingObj {private static final Logger logger = LoggerFactory.getLogger(AdvisingObj.class);public void beforeExecute(){logger.info("AdvisingObj beforeExcecute().");}public void afterExecute(){logger.info("AdvisingObj afterExecute().");}public void roundExecute(ProceedingJoinPoint joinpoint){try{logger.info("AdvisingObj before roundExecute().");joinpoint.proceed();logger.info("AdvisingObj after roundExecute().");}catch(Throwable t){}}
}
结果:
01:36:00.808 [main] INFO com.springtest.AdvisingObj - AdvisingObj before roundExecute().
01:36:00.825 [main] INFO com.springtest.AdvisedObj - AdvisedObj perform().
01:36:00.825 [main] INFO com.springtest.AdvisingObj - AdvisingObj after roundExecute().
为通知传递参数
有时候通知并不仅仅是对方法进行简单包装,还需要校验传递给方法的参数值,这时候为通知传递参数就非常有用了。
通过配置实现将被通知方法的参数传递给通知,如下指定String参数,然后在args参数中标识了将parameter作为参数。
示例:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsd"><!-- Root Context: defines shared resources visible to all other web components --><bean id="advised" class="com.springtest.AdvisedObj" /><bean id="advising" class="com.springtest.AdvisingObj" /><aop:config><aop:aspect ref="advising"><aop:pointcut id="performance" expression="execution(* com.springtest.AdvisedObj.perform(String)) and args(parameter)" /><!-- <aop:before pointcut-ref="performance" method="beforeExecute" /><aop:after pointcut-ref="performance" method="afterExecute" /> <aop:around pointcut-ref="performance" method="roundExecute" />--><aop:before pointcut-ref="performance" method="parameterExecute" arg-names="parameter" /></aop:aspect></aop:config></beans>
package com.springtest;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.springtest.AdvisedObj;
import com.springtest.AdvisingObj;public class SpringCoreTest{public static void main(String[] args){ApplicationContext ctx = new FileSystemXmlApplicationContext("//Users/... .../beans_config.xml");AdvisedObj advisedObj = (AdvisedObj)ctx.getBean("advised");advisedObj.perform("TestParameter");}
}
package com.springtest;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class AdvisedObj {private static final Logger logger = LoggerFactory.getLogger(AdvisedObj.class);public void perform(String parameter){logger.info("AdvisedObj perform(), parameter is {}.", parameter);}
}
package com.springtest;import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class AdvisingObj {private static final Logger logger = LoggerFactory.getLogger(AdvisingObj.class);public void beforeExecute(){logger.info("AdvisingObj beforeExcecute().");}public void afterExecute(){logger.info("AdvisingObj afterExecute().");}public void roundExecute(ProceedingJoinPoint joinpoint){try{logger.info("AdvisingObj before roundExecute().");joinpoint.proceed();logger.info("AdvisingObj after roundExecute().");}catch(Throwable t){}}public void parameterExecute(String parameter){logger.info("AdvisingObj parameterExecute(), parameter is {}.",parameter);}
}
通过切面引入新的功能
利用被称为引入的AOP概念,切面也可以为Spring Bean添加新方法。
利用<aop:declare-parents>元素:
示例:
添加一个新的接口及实现类:
package com.springtest;public interface ExtendedInterface {void extendedExecute();
}
package com.springtest;import com.springtest.ExtendedInterface;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class ExtendedObj implements ExtendedInterface{private static final Logger logger = LoggerFactory.getLogger(ExtendedObj.class);public void extendedExecute(){logger.info("ExtendedObj extendedExecute().");}
}
在AOP配置中,<aop:declare-parents>声明了此切面锁通知的Bean在它的对象结构中拥有新的父类型,那些Bean会实现此接口。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsd"><!-- Root Context: defines shared resources visible to all other web components --><bean id="advised" class="com.springtest.AdvisedObj" /><bean id="advising" class="com.springtest.AdvisingObj" /><bean id="extended" class="com.springtest.ExtendedObj" /><aop:config><aop:aspect ref="advising"><!-- <aop:pointcut id="performance" expression="execution(* com.springtest.AdvisedObj.perform(String)) and args(parameter)" /><aop:before pointcut-ref="performance" method="beforeExecute" /><aop:after pointcut-ref="performance" method="afterExecute" /> <aop:around pointcut-ref="performance" method="roundExecute" /><aop:before pointcut-ref="performance" method="parameterExecute" arg-names="parameter" />--><aop:declare-parents types-matching="com.springtest.AdvisedObj+" implement-interface="com.springtest.ExtendedInterface"delegate-ref="extended" /> </aop:aspect></aop:config></beans>
package com.springtest;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.springtest.AdvisedObj;
import com.springtest.AdvisingObj;
import com.springtest.ExtendedInterface;;public class SpringCoreTest{public static void main(String[] args){ApplicationContext ctx = new FileSystemXmlApplicationContext("//Users/wongrobin/all/projects/java/javaweb/ssh/SpringCoreTest/beans_config.xml");//AdvisedObj advisedObj = (AdvisedObj)ctx.getBean("advised");//advisedObj.perform("TestParameter");ExtendedInterface advisedObj = (ExtendedInterface)ctx.getBean("advised");advisedObj.extendedExecute();}
}
SpringAOP 之 @AspectJ注解切面
使用注解来创建切面是AspectJ5所引入的关键特性。AspectJ面向注解的模型可以非常简单地通过少量注解把任意类转换为切面(不需要使用Java语言扩展)。这种新特性通常称为@AspectJ。
示例:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsd"><aop:aspectj-autoproxy /><!-- Root Context: defines shared resources visible to all other web components --><bean id="advised" class="com.springtest.AspectJAnnotationAdvisedObj" /><bean id="advising" class="com.springtest.AspectJAnnotationAdvisingObj" /></beans>
<aop:aspectj-autoproxy />将在Spring上下文中创建一个AnnotationAwareAspectJAutoProxyCreator类, 它会自动代理一些Bean,这些Bean的方法需要与使用@Aspect注解的Bean所定义的切点相匹配, 因此,被代理的目标对象类和使用@Aspect注解的类都应该定义成Bean,否则无法找到它们(定义Bean:advised和advising)。
package com.springtest;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class AspectJAnnotationAdvisedObj{
private static final Logger logger = LoggerFactory.getLogger(AspectJAnnotationAdvisedObj.class);public void perform(){logger.info("AspectJAnnotationAdvisedObj perform().");}
}
package com.springtest;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;@Aspect
public class AspectJAnnotationAdvisingObj {private static final Logger logger = LoggerFactory.getLogger(AspectJAnnotationAdvisingObj.class);@Pointcut("execution(* com.springtest.AspectJAnnotationAdvisedObj.perform(..))")public void performance() {}@Before("performance()")public void beforeExecute(){logger.info("AspectJAnnotationAdvisingObj beforeExcecute().");}@AfterReturning("performance()")public void afterExecute(){logger.info("AspectJAnnotationAdvisingObj afterExecute().");}
}
@Pointcut注解用于定义一个可以在@AspectJ切面内可重用的切点。@Pointcut注解的值是一个AspectJ切点表达式,这里表示该切点必须匹配perform方法。切点的名称来源于注解所应用的方法名称。因此,该切点的民称为performance()。performance()方法的实际内容并不重要,在这里它事实上是空的,其实该方法本身只是一个标识,供@Pointcut注解依附。
@Before注解标识是前置通知方法,@AfterReturning注解标识是后置通知方法。
performance()切点的名称作为参数的值赋给了所有的通知注解,以这种方式来标识每一个通知方法应该应用在哪里。
package com.springtest;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.springtest.AspectJAnnotationAdvisedObj;
import com.springtest.AspectJAnnotationAdvisingObj;public class AspectJAnnotationTest {public static void main(String[] args){ApplicationContext ctx = new FileSystemXmlApplicationContext("//Users/wongrobin/all/projects/java/javaweb/ssh/SpringCoreTest/annotationaspectj_config.xml");AspectJAnnotationAdvisedObj advisedObj = (AspectJAnnotationAdvisedObj)ctx.getBean("advised");advisedObj.perform(); }
}
<aop:aspectj-autoproxy>仅仅使用@AspectJ注解作为指引来创建基于代理的切面,但本质上它仍然是一个Spring风格的切面。
注解环绕通知
使用@Around注解可以创建环绕通知;被环绕通知的方法必须接受一个ProceedingJoinPoint对象作为方法入参,并在对象上调用proceed()方法。
示例:
package com.springtest;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;@Aspect
public class AspectJAnnotationAdvisingObj {private static final Logger logger = LoggerFactory.getLogger(AspectJAnnotationAdvisingObj.class);@Pointcut("execution(* com.springtest.AspectJAnnotationAdvisedObj.perform(..))")public void performance() {}/*@Before("performance()")public void beforeExecute(){logger.info("AspectJAnnotationAdvisingObj beforeExcecute().");}@AfterReturning("performance()")public void afterExecute(){logger.info("AspectJAnnotationAdvisingObj afterExecute().");}*/@Around("performance()")public void roundExecute(ProceedingJoinPoint joinpoint){try{logger.info("AspectJAnnotationAdvisingObj before roundExecute().");joinpoint.proceed();logger.info("AspectJAnnotationAdvisingObj after roundExecute().");}catch(Throwable t){}}
}
执行结果:
02:44:04.540 [main] INFO c.s.AspectJAnnotationAdvisingObj - AspectJAnnotationAdvisingObj before roundExecute().
02:44:04.562 [main] INFO c.s.AspectJAnnotationAdvisedObj - AspectJAnnotationAdvisedObj perform().
02:44:04.562 [main] INFO c.s.AspectJAnnotationAdvisingObj - AspectJAnnotationAdvisingObj after roundExecute().
传递参数给所标注的通知
使用@AspectJ注解为通知传递参数,与Spring基于XML的切面声明没有太大区别。
示例:
package com.springtest;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class AspectJAnnotationAdvisedObj{
private static final Logger logger = LoggerFactory.getLogger(AspectJAnnotationAdvisedObj.class);public void perform(String parameter){logger.info("AspectJAnnotationAdvisedObj perform(), parameter is {}.", parameter);}
}
package com.springtest;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;@Aspect
public class AspectJAnnotationAdvisingObj {private static final Logger logger = LoggerFactory.getLogger(AspectJAnnotationAdvisingObj.class);@Pointcut("execution(* com.springtest.AspectJAnnotationAdvisedObj.perform(String)) && args(parameter)")public void performance(String parameter) {}@Before("performance(parameter)")public void beforeExecute(String parameter){logger.info("AspectJAnnotationAdvisingObj beforeExcecute(), parameter is {}.", parameter);}@AfterReturning("performance(parameter)")public void afterExecute(String parameter){logger.info("AspectJAnnotationAdvisingObj afterExecute(), parameter is {}.", parameter);}/*@Around("performance()")public void roundExecute(ProceedingJoinPoint joinpoint){try{logger.info("AspectJAnnotationAdvisingObj before roundExecute().");joinpoint.proceed();logger.info("AspectJAnnotationAdvisingObj after roundExecute().");}catch(Throwable t){}}*/
}
package com.springtest;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.springtest.AspectJAnnotationAdvisedObj;
import com.springtest.AspectJAnnotationAdvisingObj;public class AspectJAnnotationTest {public static void main(String[] args){ApplicationContext ctx = new FileSystemXmlApplicationContext("//Users/wongrobin/all/projects/java/javaweb/ssh/SpringCoreTest/annotationaspectj_config.xml");AspectJAnnotationAdvisedObj advisedObj = (AspectJAnnotationAdvisedObj)ctx.getBean("advised");advisedObj.perform("Parameter1"); }
}
执行结果:
03:03:19.837 [main] INFO c.s.AspectJAnnotationAdvisingObj - AspectJAnnotationAdvisingObj beforeExcecute(), parameter is Parameter1.
03:03:19.856 [main] INFO c.s.AspectJAnnotationAdvisedObj - AspectJAnnotationAdvisedObj perform(), parameter is Parameter1.
03:03:19.856 [main] INFO c.s.AspectJAnnotationAdvisingObj - AspectJAnnotationAdvisingObj afterExecute(), parameter is Parameter1.
标注引入
使用基于注解的AOP为已有的Bean引入接口。等价于<aop:declare-parents>的注解是@AspectJ的@DeclareParents。
示例:使用上一节的ExtendInterface和ExtendedObj:
package com.springtest;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.DeclareParents;@Aspect
public class AspectJAnnotationAdvisingObj {private static final Logger logger = LoggerFactory.getLogger(AspectJAnnotationAdvisingObj.class);@DeclareParents(value="com.springtest.AspectJAnnotationAdvisedObj+",defaultImpl=ExtendedObj.class)public static ExtendedInterface extended;/*@Pointcut("execution(* com.springtest.AspectJAnnotationAdvisedObj.perform(String)) && args(parameter)")public void performance(String parameter) {}@Before("performance(parameter)")public void beforeExecute(String parameter){logger.info("AspectJAnnotationAdvisingObj beforeExcecute(), parameter is {}.", parameter);}@AfterReturning("performance(parameter)")public void afterExecute(String parameter){logger.info("AspectJAnnotationAdvisingObj afterExecute(), parameter is {}.", parameter);}@Around("performance()")public void roundExecute(ProceedingJoinPoint joinpoint){try{logger.info("AspectJAnnotationAdvisingObj before roundExecute().");joinpoint.proceed();logger.info("AspectJAnnotationAdvisingObj after roundExecute().");}catch(Throwable t){}}*/
}
package com.springtest;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.springtest.AspectJAnnotationAdvisedObj;
import com.springtest.AspectJAnnotationAdvisingObj;
import com.springtest.ExtendedInterface;;public class AspectJAnnotationTest {public static void main(String[] args){ApplicationContext ctx = new FileSystemXmlApplicationContext("//Users/wongrobin/all/projects/java/javaweb/ssh/SpringCoreTest/annotationaspectj_config.xml");/*AspectJAnnotationAdvisedObj advisedObj = (AspectJAnnotationAdvisedObj)ctx.getBean("advised");advisedObj.perform("Parameter1"); */ExtendedInterface advisedObj = (ExtendedInterface)ctx.getBean("advised");advisedObj.extendedExecute(); }
}
执行结果:
03:16:30.784 [main] INFO com.springtest.ExtendedObj - ExtendedObj extendedExecute().
@DeclareParents注解由3部分组成:
- value属性等同于<aop:delcare-parents>的types-matching属性。它标识应该被引入指定接口的Bean类型。
- defaultImpl属性等同于<aop:declare-parents>的default-impl属性。它标识该类提供了所引入接口的实现。
- 由@DeclaeParents注解所标注的static属性指定了将被引入的接口。
(该注解类AspectJAnnotationAdvisingObj需要声明为Spring应用上下文中的一个Bean。)
SpringAOP 之 注入AspectJ切面
AspectJ提供了Spring AOP所不能支持的许多类型的切点。
【Spring】AOP - 面向切面相关推荐
- Java绝地求生—Spring AOP面向切面编程
Java绝地求生-Spring AOP面向切面编程 背景 动态代理 构建被代理对象 自动生成代理 调用动态代理 Spring方法 方式一:使用Spring的API接口 方式二:使用自定义类 方式三:使 ...
- Spring AOP面向切面编程
AOP面向切面编程: AOP(Aspect Oriented Programming),即面向切面编程,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公 ...
- Spring AOP 面向切面编程相关注解
Aspect Oriented Programming 面向切面编程 在Spring中使用这些面向切面相关的注解可以结合使用aspectJ,aspectJ是专门搞动态代理技术的,所以比较专业. 需要在 ...
- Spring Aop面向切面编程自动注入
1.面向切面编程 在程序原有纵向执行流程中,针对某一个或某一些方法添加通知,形成横切面的过程叫做面向切面编程 2.常用概念 原有功能:切点,pointcut 前置通知:在切点之前执行的功能,befor ...
- Spring AOP 面向切面编程
AOP 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件 ...
- Spring AOP(面向切面编程)
AOP(Aspect Oriented Programming),也就是面向切面编程,作为面向对象编程的一种补充,AOP已经成为一种比较成熟的编程方式.可以这样理解:OOP是从静态角度考虑程序结构,而 ...
- java框架013——Spring AOP面向切面编程
一.Spring AOP简介 AOP的全称是Aspect-Oriented Programming,即面向切面编程(也称面向方面编程).它是面向对象编程(OOP)的一种补充,目前已成为一种比较成熟的编 ...
- JavaEE——Spring AOP(面向切面编程)
目录 1.面向切面编程(AOP) 2.AOP术语 3.AOP类型 4.AOP 的优势 5.Spring AOP 的代理机制 6.Spring AOP 连接点 7.Spring AOP 通知类型 8.基 ...
- Spring AOP面向切面编程:理解篇(一看就明白)
一直想着怎么去通俗的讲解AOP,看了一篇文章受到了启发(https://blog.csdn.net/qukaiwei/article/details/50367761),下面我加入自己的理解,咱们来说 ...
- Spring aop面向切面编程概述
aop概述 1.AOP为Aspect Oriented Programming的缩写,意为:面向切面编程.将程序中公用代码进行抽离,通过动态代理实现程序功能的统一维护的一种技术.使代码耦合性降低,提高 ...
最新文章
- 【数据结构】平衡树 - treap
- cad打印样式ctb丢失_CAD制图软件中如何设置CAD打印样式表(CTB)?
- 一点通路由器模拟软件最新版_2019年高压电工作业考试最新版题库及答案(全部判断题)...
- 吐血整理:机器学习的30个基本概念,都在这里了(手绘图解)
- Sprint会议记录(第五组)
- 2021-01-13 Matlab求解微分代数方程 (DAE)
- 硬件基础:虚拟内存相关知识介绍?
- 动态规划与数学方程法解决楼层扔鸡蛋问题
- sqltext的参数化处理
- [新功能]文章预览功能
- 华为鸿蒙系统os新机,鸿蒙OS今日面世,华为将出新机搭载新系统入市场
- 最强大脑就是让你记得住--史上最高效的270个记忆法
- 监控视频平台LiveNVR如何给摄像头视频添加文字水印和图片水印
- [宋史学习] 取蜀将帅不利
- 实验部分小结:数据集处理部分
- 领土局本副局长蒙贿获刑5年
- org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):的三种解决方式
- 第一课 request传参
- web项目中上传的图片项目重新部署之后被清空如何解决?
- 软件需求管理用例方法 pdf_一卡通考勤门禁管理软件需求描述