7、spring 入门—Spring对AspectJ的支持
来源:互联网 发布:手机防吸费软件 编辑:程序博客网 时间:2024/05/29 07:37
@AspectJ的风格类似纯java注解的普通java类
Spring可以使用AspectJ来做切入点解析
AOP的运行时仍旧是纯的SpringAOP,对AspectJ的编译器或者织入无依赖性
2.对@AspectJ支持可以使用XML或Java风格的配置
@Configuration
@EnableAspectJAutoProxy
public class AppConfig{}
<aop:aspectj-autoproxy/>
3.@AspectJ切面使用@AspectJ注解配置,拥有@Aspect的任何bean将被Spring自动识别并应用。
用@AspectJ注解的类可以有方法和字段,他们也可能包括切入点(pointcut),通知(Advice)和引入(introduction)声明
4.@AspectJ注解是不能够通过类路径自动检测发现的,所以需要配合使用@Conponent注释或者在XML中配置bean
5.一个类中的@AspectJ注解标始它为一个切面,并且将自己从自动代理中排除
6.AspectJ是编译期的AOP,检查代码并匹配连接点与切入点的代价是昂贵的。
一个好的切入点应该包括以下;
①选择特定类型的连接点,如:execution,get,set,call,handler
②确定连接点范围,如:within,withincode
③匹配上下文信息,如;this.targe,@annotation
一个切入点通过一个普通的方法定义来提供,并且切入点表达式使用@Pointcut注解,方法返回类型必须为void
定义一个名为“anyOldTransfer”方法,这个切入点将匹配任何名为“transfer”的方法的执行,如:
@Pointcut("execution(* transfer(..))")
private void anyOldTransfer(){}
组合pointcut:
切入点表达式可以通过&&、||和!进行组合,也可以通过名字引用切入点表达式
通过组合,可以建立更加复杂的切入点表达式
通知
1.@Before("表示式、连接点方法名()")
2.@AfterReturing 可以使用returing绑定返回值 Object
3.@AfterThrowing throwing同上
4.@After finally
5.@Around 第一个参数必须是ProceedingJoinPoint proceed(),proceed(Object[])
//相关代码——(上):
@spring-aop-aspectj.xml
<context:component-scan base-package="com.imooc.aop.aspectj" />
<aop:aspectj-autoproxy />
@UnitTestBase.java
//省略代码...
@MoocBiz.java
package com.imooc.aop.aspectj.biz;
@Service
public class MoocBiz {
public String save(String arg){
System.out.println("MoocBiz save:"+arg);
// throw new RuntimeException("Save failed!");
return "Save success!";//作用在AfterReturning或Around Object obj=pjp.proceed();
}
}
@TestAspectJ.java
@RunWith(BlockJUnit4ClassRunner.class)
public class TestAspectJ extends UnitTestBase{
public TestAspectJ(){
super("classpath:spring-aop-aspectj.xml");
}
@Test
public void test(){
MoocBiz biz=getBean("moocBiz");
biz.save("This is test.");
}
}
@MoocAspect.java
package com.imooc.aop.aspectj;
@Component
@Aspect
public class MoocAspect {
@Pointcut("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))")//方法二
public void pointcut(){}
@Pointcut("within(com.imooc.aop.aspectj.biz.*)")
public void bizPointcut(){}
//相关代码——(下):
// @Before("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))")//方法一
@Before("pointcut()")//方法二
public void before(){
System.out.println("Before.");
}
@AfterReturning(pointcut="bizPointcut()",returning="returnValue")
public void afterReturning(Object returnValue){
System.out.println("AfterReturning:"+returnValue);
}
@AfterThrowing(pointcut="pointcut()",throwing="e")
public void afterThrowing(RuntimeException e){
System.out.println("AfterThrowing:"+e.getMessage());
}
@After("pointcut()")
public void after(){
System.out.println("After.");
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable{
syso("Around 1.");
Object obj=pjp.proceed();//调用真正的方法
System.out.println("Around 2.");
System.out.println("Around:"+obj);
return obj;
}
}
//输出:
Around 1.
Before.
MoocBiz save:This is test.
Around 2.
Around:Save success!
After.
AfterReturning:Save success!
Spring 中通知的类型:
Around org.aopalliance.intercept.MethodInterceptor 栏截对目标对象方法的调用
Before org.springframework.aop.MethodBeforAdvice 在目标方法被调用之前调用
After org.springframework.aop.AfterReturningAdvice 当目标方法被调用之后调用
Thorws org.springframework.aop.ThrowsAdvice 当目标方法抛出异常时调用
程序正常执行顺序:
执行前 -环绕通知 Around
执行前 - 通知 Before
POINT - 切入点 方法前执行 @Before
POINT - 切入点 环绕方法前执行 @Around
切入点异常处理通知 @AfterThrowing
异常处理通知 Thorws
给advice传递参数
1.args()
(即在通知中获取符合切入点的方法中的参数)
2.自定义注解
(即在通知中获取符合切入点的方法被注解标注的值)
使用args():
//定义目标对象
@Component
public class A{
//符合切入点的方法
public void print(String name){
System.out.println(name);
}
}
//定义切面
@Aspect
@Component
public class asp{
@Pointcut(execution(* com.own.A.*(..)) && args(arg))
public void pointcut1(String arg){}
//使用args()的方式要保证args()括号内的参数名要与定义切入点的参数名一致.
//@Before注解中引入切入点并配上参数(不需要类型).
@Before("pointcut1(arg)")
public void before(String arg){
System.out.println("before:"+arg);
}
//或者
@Before(execution(* com.own.A.*(..)) && args(arg))
public void before(String arg){
System.out.println("before:"+arg);
}
}
<beans..>
<aop:aspectj-autoproxy></aop:aspectj>
</beans>
测试类中:
A a=(A)context.getBean("a");
a.printl("param")
控制台显示:
before:param
param
给advice传递参数
@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation() && args(account,..)")
public void validateAccount(Account account) {
// ...
}
@Pointcut("com.xyz.myapp.SystemArchitecture.dataAccessOperation() && args(account,..)")
private void accountDataAccessOperation(Account account) {}
@Before("accountDataAccessOperation(account)")
public void validateAccount(Account account) {
// ...
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Auditable {
AuditCode value();
}
@Before("com.xyz.lib.Pointcuts.anyPublicMethod() && @annotation(auditable)")
public void audit(Auditable auditable) {
AuditCode code = auditable.value();
// ...
}
Advice的参数及泛型
.Spring AOP可以处理泛型类的声明和使用方法的参数
public interface Sample<T> {
void sampleGenericMethod(T param);
void sampleGenericCollectionMethod(Collection>T> param);
}
@Before("execution(* ..Sample+.sampleGenericMethod(*)) && args(param)")
public void beforeSampleMethod(MyType param) {
// Advice implementation
}
@Before("execution(* ..Sample+.sampleGenericCollectionMethod(*)) && args(param)")
public void beforeSampleMethod(Collection<MyType> param) {
// Advice implementation
}
Advice参数名称
.通知和切入点注解有一个额外的“argNames”属性,它可以用来指定所注解的方法的参数名
@Before(value="com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && @annotation(auditable)",
argNames="bean,auditable")
public void audit(Object bean, Auditable auditable) {
AuditCode code = auditable.value();
// ... use code and bean
}
.如果第一参数是JoinPoint,ProceedingJoinPoint,JoinPoint.StaticPart,那么可以忽略它
@Before(value="com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && @annotation(auditable)",
argNames="bean,auditable")
public void audit(JoinPoint jp, Object bean, Auditable auditable) {
AuditCode code = auditable.value();
// ... use code, bean, and jp
}
Introductions
.允许一个切面声明一个通知对象实现指定接口,并且提供了一个接口实现类来代表这些对象
.Introduction使用@DeclareParents进行注解,这个注解用来定义匹配的类型拥有一个新的parent
Introductions
.例如:给定一个接口UsageTracking ,并且该接口拥有DefaultUsageTracked的实现,接下来的切面声明了所有的service接口的实现都实现了UsageTracked接口
@Aspect
public class UsageTracking {
@DeclareParents(value="com.xzy.myapp.service.*+", defaultImpl=DefaultUsageTracked.class)
public static UsageTracked mixin;
@Before("com.xyz.myapp.SystemArchitecture.businessService() && this(usageTracked)")
public void recordUsage(UsageTracked usageTracked) {
usageTracked.incrementUseCount();
}
}
切面实例化模型
.这是一个高级主题
.“perthis”切面通过制定@Aspect注解perthis子句实现
.每个独立的service对象执行时都会创建一个切面实例
.service对象的每个方法在第一次执行的时候创建切面实例,切面service对象失效的同时失效
@Aspect("perthis(com.xyz.myapp.SystemArchitecture.businessService())")
public class MyAspect {
private int someState;
@Before(com.xyz.myapp.SystemArchitecture.businessService())
public void recordServiceUsage() {
// ...
}
}
AspectJ小结
.配置@AspectJ
.Pointcut
.Adivce
- 7、spring 入门—Spring对AspectJ的支持
- Spring对AspectJ的支持
- 实例简述Spring AOP之对AspectJ语法的支持
- 实例简述Spring AOP之对AspectJ语法的支持
- 实例简述Spring AOP之对AspectJ语法的支持
- Spring AOP支持的AspectJ语法详解
- java spring aop 支持的AspectJ 切面
- Spring AOP支持的AspectJ语法
- Spring入门(Spring对JSR支持的说明)
- Spring AOP @AspectJ 入门实例
- Spring AOP @AspectJ 入门实例
- Spring Aop入门之Aspectj
- Spring AOP @AspectJ 入门实例
- Spring AOP @AspectJ 入门实例
- Spring AOP @AspectJ 入门实例
- spring AspectJ的Execution
- Spring---AspectJ的AOP
- spring的aspectj简介
- VMware Workstation 12 Player CPU占用100%
- (DT系列五)Linux kernel 是怎么将 devicetree中的内容生成plateform_device
- offsetof,container_of
- Jsonp跨域
- 20161109 ArrayList set add方法 替换对应位置数据
- 7、spring 入门—Spring对AspectJ的支持
- Android系统证书platform.x509.pem,platform.pk8转换为.keystore文件
- Android Studio中两个让初学者崩溃菜单
- (DT系列六)devicetree中数据和 struct device有什么关系
- 软件工程学习总结(1)——软件测试工具详解
- c语言sizeof()在32位及64位系统的区别
- Webpack入门——使用Webpack打包Angular项目的一个例子
- Java多线程之Lock的使用
- Swift3 - Result of call '***' is unused