SpringAOP–基与@Aspect注解的aop
demo
@Aspect
public class AspectConfig {
@Pointcut(value = "execution(* com.poog.code..*.*Test(..)")
public void test(){}
@Before(value = "test()")
public void beforeAdvise(){
System.out.println("before advise");
}
@After(value = "test()")
public void afterAdivise(){
System.out.println("after advise");
}
@Around(value = "test()")
public void aroundAdvise(ProceedingJoinPoint joinPoint){
try {
System.out.println("around before advise");
joinPoint.proceed();
System.out.println("around after advise");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
public interface TestInterfave {
public void dosomeTest();
public void doanotherTest();
public void a();
public void b();
}
public class TestImpl implements TestInterfave {
public void dosomeTest() {
System.out.println("dosomeTest");
}
public void doanotherTest() {
System.out.println("doanotherTest");
}
public void a() {
System.out.println("a");
}
public void b() {
System.out.println("b");
}
}
输出结果
around before advise
before advis
dosomeTest
after advise
around after advise
----------------------
around before advise
before advis
doanotherTest
after advise
around after advise
在这个demo中我们需要在配置文件中加入一项配置,代表框架会自动识别并且处理@Aspect注解
<aop:aspectj-autoproxy/>
此标签使用AspectJAutoProxyBeanDefinitionParser来解析
1.注册AnnotationAwareAspectJAutoProxyCreator类,该类负责切面类的解析,代理对象的创建,是AOP的核心类
2.解析 aop:aspectj-autoproxy/ 的两个属性
2.1 expose-proxy:是否暴露当前对象
对于方法内部调用其他方法,如果方法内部的方法也需要增强,则需要将这个属性设置为true,来将内部方法暴露出来
2.2proxy-target-class:默认值为false
当我们需要cglib动态代理时,则将此属性设置为true
加载Aspect切面和Advisor
在上面注册的AnnotationAwareAspectJAutoProxyCreator这个bean最上层是继承了BeanPostProcess,我们知道在IOC创建bean的时候会去调用后处理器来执行一些增强逻辑
1.postProcessBeforeInstantiation
这个方法是在AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator中被实现的,并且这个方法会在IOC - createBean之前调用,如果这个方法返回一个bean,则创建bean的过程会被短路,不会走正常的逻辑
一般情况是返回NULL,如果用户自定义了一个TargetSource,以用户自定义的逻辑来处理目标实例的话,就会返回处理后的bean
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
2.postProcessAfterInitialization
这个后处理器会在IOC创建AnnotationAwareAspectJAutoProxyCreator这个bean时,做完初始化逻辑后去调用
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
这个方法的重点就是wrapIfNecessary
wrapIfNecessary()
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
//1.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//2.
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
1.getAdvicesAndAdvisorsForBean
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
1.1findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//1.11 获取所有的advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//1.12 找到可以用在当前beanName的advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//1.13 给advisor排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
1.11 findCandidateAdvisors
xxxxxxxxxx protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. //调用父类的advisor //加载的是配置文件中的advisor //步骤:获取类型为advisor的beanName,然后通过getBean方法获取到bean并加入到集合中 List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. if (this.aspectJAdvisorsBuilder != null) { //获取注解形式的advisor //步骤:获取工厂里的所有beanName,遍历查找带有@Aspect注解的bean //在这个bean中获取Advisor,即*1. advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors;}
*1.获取advisor
即buildAspectJAdvisors中的List classAdvisors = this.advisorFactory.getAdvisors(factory);
这个方法是个重点
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
//a.
for (Method method : getAdvisorMethods(aspectClass)) {
//b.
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
......
return advisors;
}
a.该方法获取到此AspectClass除Pointcut标记的方法以外的所有方法
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new LinkedList<Method>();
ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
}
});
Collections.sort(methods, METHOD_COMPARATOR);
return methods;
}
b.提取上述方法所对应的advisor
分为两个步骤
1.获取pointcut切点注解信息
2.根据切点注解信息生成advisor
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 1.
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
//2.
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
1.getPointcut()
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
//这个方法获取到Before、Around、After、 AfterReturning、AfterThrowing、Pointcut的注解信息aspectJAnnotation
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
//设置表达式,就是demo中的execution
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
//返回生成的ajexp对象,这个对象里面包含了传进来的除pointcut注解以外的方法和匹配表达式,
return ajexp;
}
2.return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName)
看一下这个 InstantiationModelAwarePointcutAdvisorImpl 类
该方法前半部分就是将上面的参数赋值一遍,重点在主要逻辑的
instantiateAdvice(this.declaredPointcut);
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
this.declaredPointcut = declaredPointcut;
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;
//不看
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it's not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
//主要逻辑
else {
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
instantiateAdvice
这个方法从advisor工厂里面拿到一个advise,因为一个advisor是对应一个advise的
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
}
getAdvise
这个方法看着很长,其实逻辑很清楚
主要就是根据aspectJAnnotation的类型创建不同的advisor,因为你传进来的类型可能是@Before,或者@After等等
所有分为了五种逻辑创建:
AspectJMethodBeforeAdvisor,AspectJAfterAdvisor,AspectJAfterRunningAdvisor,AspectJAfterThrowingAdvisor,AspectJAroudAdvisor
@Override
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
1.12 findAdvisorsThatCanApply()
匹配合适beanName的advisor
参数中candidateAdvisors为上一步匹配到的所有advisors
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
然后对advisors进行选择 AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass)
这个方法将advisor分为了两种,IntroductionAdvisor和PointcutAdvisor
IntroductionAdvisor是类级别的增强,和切点无关,主要是为了给类追加更多的方法
这种只需要持有classFilter即可
PointcutAdvisor是方法级别的增强,和切点有关,主要是为了拦截方法
这种需要classFilter和methodMatch,因为PointcutAdvisor内部持有一个pointcut,而pointcut就是由classFilter和methodMatch组成的
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
pointcutAdvisor类型的canApply逻辑可分为三步
1.获取advisor中的pointCut
2.获取pointCut中的classFilter,匹配当前targetClass
3.获取pointCut中的methodMatcher,遍历匹配当前targetClass中的所有method
## 2.创建代理creatProxy()
```java
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
//1.创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
//将生产资料放进代理工厂里面
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//2.将interceptor统一适配为advisors
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//3.获取代理,这个逻辑看另一个aop笔记
return proxyFactory.getProxy(getProxyClassLoader());
}
2.2将interceptor统一适配为advisors
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// Handle prototypes correctly...
Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors.length > 0) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
if (logger.isDebugEnabled()) {
int nrOfCommonInterceptors = commonInterceptors.length;
int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
//适配方法
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
适配方法,将各种interceptor也就是advise适配为advisor
将传进来的增强器分为三类
1.advisor类,直接返回
2.advise类型,包装为DefaultPointcutAdvisor类
advise又分为两种:MethodInterceptor和其他例如MethodBeforeAdvice,AfterReturningAdvice,ThrowsAdvice
```java
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}