前言
继上篇《Spring之AOP-先导篇》,我们对Spring AOP有了一个全面的初步了解之后,本篇我们将从源码级别解决上篇剩余的问题。
- @EnableAspectJAutoProxy
- Spring AOP具体怎么实现的?
- jdk代理一定比cglib代理慢吗?
Spring Transaction Management是Spring AOP切面很好的例子,在笔者的《Transaction Management源码阅读路径》也有提及。
使用的代码
和《Transaction Management源码阅读路径》使用的代码差不多,使用mysql、mybatis-plus、spring-boot。
import lombok.SneakyThrows;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableTransactionManagement
@MapperScan(basePackages = {"com.whf.spring.dao"})
public class Application {
@SneakyThrows
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
import com.whf.spring.service.business.TryService;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@WebAppConfiguration
class ApplicationTests {
@Autowired
private TryService tryService;
@Test
void testTransaction() {
tryService.test();
}
}
import com.whf.spring.annotation.SimpleAnnotation;
import com.whf.spring.service.UserService;
import com.whf.spring.service.business.TryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Scope
@Slf4j
public class TryServiceImpl implements TryService {
@Autowired
private UserService userService;
@Override
@SimpleAnnotation
@Transactional(rollbackFor = Exception.class)
public void test() {
log.info("执行业务");
userService.test();
}
}
import com.whf.spring.dao.UserDao;
import com.whf.spring.entity.UserDo;
import com.whf.spring.service.UserService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, UserDo> implements UserService {
@Override
public void test() {
this.selectById(1);
throw new RuntimeException();
}
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SimpleAnnotation {
}
import com.whf.spring.annotation.SimpleAnnotation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Slf4j
@Component
public class SimpleAspect {
@Around("@annotation(simpleAnnotation)")
@SneakyThrows
public Object simpleAround(ProceedingJoinPoint pjp, SimpleAnnotation simpleAnnotation) {
log.info("进入simpleAround");
Object proceed = pjp.proceed();
return proceed;
}
}
@EnableAspectJAutoProxy
《Spring之AOP-先导篇》中有提到启用@AspectJ支持可以在java配置类上加上@EnableAspectJAutoProxy注解。下面我们来了解下。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* 指示是否创建基于子类(CGLIB)的代理,而不是基于标准Java接口的代理。默认值为false。
*/
boolean proxyTargetClass() default false;
/**
* 指示AOP框架应将代理公开为ThreadLocal,以便通过org.springframework.aop.framework.AopContext进行检索。
* 默认情况下关闭,即不保证AopContexr访问将正常工作。
* @since 4.3.1
*/
boolean exposeProxy() default false;
}
AspectJAutoProxyRegistrar
根据给定的@EnableAspectJAutoProxy注解,根据当前BeanDefinitionRegistry注册AnnotationAwareAspectJAutoProxyCreator。
- 可以看到使用的代码中没有显示使用
@EnableAspectJAutoProxy,所以AnnotationMetadata的className为org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$AspectJAutoProxyingConfiguration$CglibAutoProxyConfiguration很明显是spring boot的自动装配。BeanDefinitionRegistry为DefaultListableBeanFactory。 - 注册的APC为AnnotationAwareAspectJAutoProxyCreator并且proxyTargetClass=true
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* 根据在@Configuration类上的@EnableAspectJAutoProxy.proxyTargetClass() 属性值注册、升级、配置AspectJ APC(auto proxy creator)。
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 这里注册的是AnnotationAwareAspectJAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
// 这里为true,自动装配CglibAutoProxyConfiguration中指定的
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
// AnnotationAwareAspectJAutoProxyCreator#proxyTargetClass=true
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
//这里为false
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
Spring AOP具体怎么实现的?
时序图
从注册APC到生成代理类并创建代理实例的时序图如下:
下面我们简单描述下步骤:
-
我们从AbstractApplicationContext#refresh方法的
invokeBeanFactoryPostProcessors(beanFactory);开始,调用bean工厂后处理器,从这里进入会调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());进而对APC进行注册。 -
进入AspectJAutoProxyRegistrar#registerBeanDefinitions进行对APC的注册,这里注册的APC为
AnnotationAwareAspectJAutoProxyCreator。至于为啥会进入这里前面的“@EnableAspectJAutoProxy章节”已经提到了。注意这里自动装配的proxyTargetClass为true。 -
bean工厂后处理器已经调用完成,下面我们的关注点就是被代理的bean进行实例化(包括生成代理类和创建代理实例)了,所以进入AbstractApplicationContext#
finishBeanFactoryInitialization(beanFactory);完成对非懒初始化的单例进行实例化。 -
进入DefaultListableBeanFactory#preInstantiateSingletons进行实例化。
-
进入
AbstractAutoProxyCreator实现类为AnnotationAwareAspectJAutoProxyCreator是一种BeanPostProcessor对bean实例化后期进行处理,这里调用postProcessAfterInitialization方法,如果bean被子类定义作为一个代理,使用一个被配置的interceptor创建代理。 -
进入
AbstractAutoProxyCreator的wrapIfNecessary,如果需要包装被给的bean,例如,如果它是合适被代理。可以有多个specificInterceptor行成链式代理,这里包含了 {BeanFactoryTransactionAttributeSourceAdvisor,InstantiationModelAwarePointcutAdvisor,DefaultPointcutAdvisor}。(这里说下DefaultPointcutAdvisor,DefaultPointcutAdvisor的Advice是ExposeInvocationInterceptor类,作用是在调用代理对象方法时,将相关信息存入ThreadLocal,以在多个advisor间进行传递。) -
调用AopUtils#canApply,判断发现的advisors是否能被应用,返回false的话该advisor就不加入eligibleAdvisors,targetClass就不会被该advisor代理。
-
返回AbstractAutoProxyCreator#wrapIfNecessary,进行找到了所有能使用的advisors。下面要准备进行代理了。
-
调用DefaultAopProxyFactory#createAopProxy,根据被给的AOP配置创建AopProxy。这里使用了cglib来生成代理。
-
调用CglibAopProxy#getProxy,生成具体代理。
-
返回至
AbstractAutoProxyCreator的wrapIfNecessary,已经代理实例已经创建好了,返回之后注入。
以上就是一个单例bean从注册APC到生成代理类并创建代理实例的大致步骤,核心类为AspectJAutoProxyRegistrar、AbstractAutoProxyCreator、DefaultAopProxyFactory、CglibAopProxy,都有在子章节中详细的介绍。
AbstractAutoProxyCreator
{@link org.springframework.beans.factory.config.BeanPostProcessor}实现使用AOP代理包装合适的bean,在调用bean本身之前委托给特定的拦截器。
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
/**
* 子类的方便常量:不需要代理的返回值。
* @see #getAdvicesAndAdvisorsForBean
*/
@Nullable
protected static final Object[] DO_NOT_PROXY = null;
/**
* Convenience constant for subclasses: Return value for
* "proxy without additional interceptors, just the common ones".
* 子类的方便常量:返回没有额外的拦截器只有普通的拦截器的返回值。
* @see #getAdvicesAndAdvisorsForBean
*/
protected static final Object[] PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS = new Object[0];
/** Logger available to subclasses. */
protected final Log logger = LogFactory.getLog(getClass());
/** Default is global AdvisorAdapterRegistry. */
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
/**
* 指示是否应冻结代理。重写父类以防止配置过早冻结。
*/
private boolean freezeProxy = false;
/** 默认没有公共拦截器 */
private String[] interceptorNames = new String[0];
private boolean applyCommonInterceptorsFirst = true;
@Nullable
private TargetSourceCreator[] customTargetSourceCreators;
@Nullable
private BeanFactory beanFactory;
private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);
/** 代理类 **/
private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
/** 被建议的beans false表示advise bean **/
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
}
wrapIfNecessary
如果需要包装被给的bean,例如,如果它是合适被代理。
这里的bean为TryServiceImpl
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;
}
// 创建代理如果有advice
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
//把需要代理的bean进行put value为true
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 根据得到的specificInterceptors生成代理
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;
}
DefaultAopProxyFactory
默认AopProxyFactory的实现,创建CGLIB代理或者JDK动态代理。
这里前面有提到config.isProxyTargetClass()为true。切面注解使用在类上所以会选择cglib代理。
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
/**
* 确定提供的AdvisedSupport是否只指定了SpringProxy接口(或者根本没有指定代理接口)。
*/
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
}
CglibAopProxy
Spring AOP框架的基于CGLIB的AopProxy实现。这种类型的对象应该通过代理工厂获得,代理工厂由AdvisedSupport对象配置。这个类是Spring的AOP框架内部的,客户端代码不需要直接使用它。DefaultAopProxyFactory将在必要时自动创建基于CGLIB的代理,例如代理目标类(有关详细信息,请参阅attendant javadoc)。如果底层(目标)类是线程安全的,那么使用该类创建的代理是线程安全的。
class CglibAopProxy implements AopProxy, Serializable {
// CGLIB索引数组索引常量。
private static final int AOP_PROXY = 0;
private static final int INVOKE_TARGET = 1;
private static final int NO_OVERRIDE = 2;
private static final int DISPATCH_TARGET = 3;
private static final int DISPATCH_ADVISED = 4;
private static final int INVOKE_EQUALS = 5;
private static final int INVOKE_HASHCODE = 6;
/** Logger available to subclasses; static to optimize serialization. */
protected static final Log logger = LogFactory.getLog(CglibAopProxy.class);
/** 跟踪我们为fianl methods验证的类。*/
private static final Map<Class<?>, Boolean> validatedClasses = new WeakHashMap<>();
/** 用于配置此代理的配置*/
protected final AdvisedSupport advised;
@Nullable
protected Object[] constructorArgs;
@Nullable
protected Class<?>[] constructorArgTypes;
/** 在Advised方法上使用的Dispatcher */
private final transient AdvisedDispatcher advisedDispatcher;
private transient Map<Method, Integer> fixedInterceptorMap = Collections.emptyMap();
private transient int fixedInterceptorOffset;
public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
this.advised = config;
this.advisedDispatcher = new AdvisedDispatcher(this.advised);
}
}
getProxy
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
// 这里为TryServiceImpl
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
// 代理的父类
Class<?> proxySuperClass = rootClass;
// 查看代理类名称是否包含cglib类分隔符
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// 验证类,根据需要编写日志信息。
validateClassIfNecessary(proxySuperClass, classLoader);
// 配置 CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// 生成代理类并创建代理实例。callbacks就是被代理的方法拦截时会被执行的逻辑。
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}