用法
基于注解
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
}
切面:连接点和我们的切点以及我们的通知所在的那个类称为切面
package org.xyz;
import org.aspectj.lang.annotation.Aspect;
@Aspect
@component
public class NotVeryUsefulAspect {
}
Pointcut:切点,连接点的集合
Pointcut:连接点,在spring AOP中,连接点的最小单位称之为方法,每一个方法我们称之为一个方法,一个表达式可以表达成多个连接点,多个连接点组合在一起称之为切点。
通知:@before、@after等等,切入切点的时机和切入切点的内容。
package com.xyz.someapp;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
@component
public class SystemArchitecture {
/
* A join point is in the web layer if the method is defined
* in a type in the com.xyz.someapp.web package or any sub-package
* under that.
/
@Pointcut("within(com.xyz.someapp.web..)")
public void inWebLayer() {}
/
* A join point is in the service layer if the method is defined
* in a type in the com.xyz.someapp.service package or any sub-package
* under that.
/
@Pointcut("within(com.xyz.someapp.service..)")
public void inServiceLayer() {}
/
* A join point is in the data access layer if the method is defined
* in a type in the com.xyz.someapp.dao package or any sub-package
* under that.
/
@Pointcut("within(com.xyz.someapp.dao..)")
public void inDataAccessLayer() {}
/
* A business service is the execution of any method defined on a service
* interface. This definition assumes that interfaces are placed in the
* "service" package, and that implementation types are in sub-packages.
*
* If you group service interfaces by functional area (for example,
* in packages com.xyz.someapp.abc.service and com.xyz.someapp.def.service) then
* the pointcut expression "execution(* com.xyz.someapp..service..(..))"
* could be used instead.
*
* Alternatively, you can write the expression using the 'bean'
* PCD, like so "bean(Service)". (This assumes that you have
* named your Spring service beans in a consistent fashion.)
*/
@Pointcut("execution( com.xyz.someapp..service..(..))")
public void businessService() {}
/*
* A data access operation is the execution of any method defined on a
* dao interface. This definition assumes that interfaces are placed in the
* "dao" package, and that implementation types are in sub-packages.
*/
@Pointcut("execution( com.xyz.someapp.dao..(..))")
public void dataAccessOperation() {}
}
基于xml
<aop:aspectj-autoproxy/>
<bean id="myAspect" class="org.xyz.NotVeryUsefulAspect">
<!-- configure properties of the aspect here -->
</bean>
<aop:config>
<aop:advisor
pointcut="com.xyz.someapp.SystemArchitecture.businessService()"
advice-ref="tx-advice"/>
</aop:config>
<tx:advice id="tx-advice">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
切入点表达式关键词:
1)execution:用于匹配子表达式。
//匹配com.cjm.model包及其子包中所有类中的所有方法,返回类型任意,方法参数任意
@Pointcut("execution(* com.cjm.model..*.*(..))")
public void before(){}
2)within:用于匹配连接点所在的Java类或者包。
//匹配Person类中的所有方法
@Pointcut("within(com.cjm.model.Person)")
public void before(){}
//匹配com.cjm包及其子包中所有类中的所有方法
@Pointcut("within(com.cjm..*)")
public void before(){}
3) this:用于向通知方法中传入代理对象的引用。
@Before("before() && this(proxy)")
public void beforeAdvide(JoinPoint point, Object proxy){
//处理逻辑
}
4)target:用于向通知方法中传入目标对象的引用。
@Before("before() && target(target)
public void beforeAdvide(JoinPoint point, Object proxy){
//处理逻辑
}
5)args:用于将参数传入到通知方法中。
@Before("before() && args(age,username)")
public void beforeAdvide(JoinPoint point, int age, String username){
//处理逻辑
}
6)@within :用于匹配在类一级使用了参数确定的注解的类,其所有方法都将被匹配。
@Pointcut("@within(com.cjm.annotation.AdviceAnnotation)") - 所有被@AdviceAnnotation标注的类都将匹配
public void before(){}
7)@target :和@within的功能类似,但必须要指定注解接口的保留策略为RUNTIME。
@Pointcut("@target(com.cjm.annotation.AdviceAnnotation)")
public void before(){}
8)@args :传入连接点的对象对应的Java类必须被@args指定的Annotation注解标注。
@Before("@args(com.cjm.annotation.AdviceAnnotation)")
public void beforeAdvide(JoinPoint point){
//处理逻辑
}
9)@annotation :匹配连接点被它参数指定的Annotation注解的方法。也就是说,所有被指定注解标注的方法都将匹配。
@Pointcut("@annotation(com.cjm.annotation.AdviceAnnotation)")
public void before(){}
10)bean:通过受管Bean的名字来限定连接点所在的Bean。该关键词是Spring2.5新增的。
@Pointcut("bean(person)")
public void before(){}
Spring完成aop的原理:并不是getbean的时候把目标对象转化成代理对象,而是初始化的时候通过调用spring中的BeanPostProcessors,创建一个代理对象,存放在singletonObjects这个map集合中。