在启动类上配置@EnableAspectJAutoProxy 注解表示开启aop。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy { boolean proxyTargetClass() default false; boolean exposeProxy() default false; }
AspectJAutoProxyRegistrar类的主要作用是将AnnotationAwareAspectJAutoProxyCreator.class注册到容器。这里是aop的主要实现逻辑。
AnnotationAwareAspectJAutoProxyCreator是BeanPostProcessor的子接口。
AnnotationAwareAspectJAutoProxyCreator的抽象父类AbstractAutoProxyCreator是关键代码。
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
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;
}
//给定的类是否为基础设施类 它不应该被代理,或者配置了制定的bean不需要自动代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
//如果存在增强方法则创建代理
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//这里是关键
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;
}
我们回过头来看当创建bean时,AbstractAutowireCapableBeanFactory.doCreateBean()
里面有一句代码initializeBean(beanName, exposedObject, mbd);这里就是BeanPostProcessor 实现类被执行的地方。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//执行Before方法
//这里当配置了 TargetSource 时才会创建代理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//执行after方法
//平时一般用的代理都是这里取创建 这里就会执行上面提到的wrapIfNecessary方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
@Override
@Nullable
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();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//这里解析被@Aspect修饰的类 解析出增强器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//这里从增强器中过滤满足的条件的Advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
//这里是注解解析
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
//这里面有个方法就是获取切点的方法
//其主要目的就是获取 @Before @Pointcut 等注解的内容
@Nullable
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
现在回到createProxy这里。
这里就会涉及到是使用jdk方式和cglib的方式。如果目标实现了接口,默认则采用jdk动态代理方式,当然也可以强制使用cglib。proxyTargetClass配置为true即可。如果目标对象没实现接口,则采用cglib。
总结下:当配置了@EnableAspectJAutoProxy时,表示开启了aop。这时会将AnnotationAwareAspectJAutoProxyCreator.class注册到spring容器,这个类的抽象父类才是实现代理的主要方法。这个类其实就是BeanPostProcessor的实现线类。当执行到postProcessAfterInitialization时,会首先解析@Aspect修饰的类。说白了就是要知道哪里需要切面,怎么切。将所有切点找出来加入缓存,然后判断当前类是否符合该其中的切点,符合则创建代理类。实际上你注入的则就时对应的代理类,执行也值执行代理类。