前记
闲来无事写的,貌似距离上一篇都快过去一年了...
环境:spring版本5.1.8
基于注解版
技术不行AND文字不好描述,只看主流程,具体的各位大佬们自己研究研究
1、AopDemo
Demo相信大家都看的懂了。用起来挺简单。需要注意的是切面类要加上@Aspect
注解,不然Spring不知道哪个是切面类喲;如果是xml配置版,需要加上<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
,如果是注解版,需要在配置类加上@EnableAspectJAutoProxy
注解;如果需要使用JoinPoint joinPoint
参数,则必须放在第一个位置。
/**
* 测试类
*/
@Configuration
@EnableAspectJAutoProxy
public class Test {
@Bean
public AopService aopService() {
return new AopService();
}
@Bean
public AopAspect aopAspect() {
return new AopAspect();
}
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Test.class);
AopService aopService = ac.getBean(AopService.class);
aopService.div(2, 1);
ac.close();
}
}
/**
* AOP类
*/
@Aspect
@Component
public class AopAspect {
@Pointcut("execution(* com.ricky.blog.AopService.*(..))")
public void point() {
}
@Before("point()")
public void before(JoinPoint joinPoint) {
System.out.println("before-" + joinPoint.getSignature().getName());
}
@After("point()")
public void After(JoinPoint joinPoint) {
System.out.println("After-" + joinPoint.getSignature().getName());
}
@AfterReturning("point()")
public void AfterReturning(JoinPoint joinPoint) {
System.out.println("AfterReturning-" + joinPoint.getSignature().getName());
}
@AfterThrowing("point()")
public void AfterThrowing(JoinPoint joinPoint) {
System.out.println("AfterThrowing-" + joinPoint.getSignature().getName());
}
}
/**
* 服务类
*/
public class AopService {
public int div(int num1, int num2) {
System.out.println(num1 / num2);
return num1 / num2;
}
}
运行结果:
before-div
2
After-div
AfterReturning-div
2、个人见解的原理分析
2.1 @EnableAspectJAutoProxy
既然一定要开启@EnableAspectJAutoProxy(Starting from Version 3.1)
才能开启AOP功能,那我们就从这个注解入手吧~
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* 这个貌似是设置实现了接口类是否走cglib,默认不走。
*/
boolean proxyTargetClass() default false;
/**
* 这个笔者不知道干什么用的,暂时无视。
*/
boolean exposeProxy() default false;
}
可以发现EnableAspectJAutoProxy
通过@Import(Starting from Version 3.0)
导入了AspectJAutoProxyRegistrar(Starting from Version 3.1)
,看名字应该是自动代理注册器
的意思。从版本上来看,只要spring版本在3.1之上就使用注解版的AOP代理了~
2.2 AspectJAutoProxyRegistrar
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
2.2.1 简单分析一下ImportBeanDefinitionRegistrar(Starting from Version 3.1)
接口
从代码上可以看到AspectJAutoProxyRegistrar
实现了ImportBeanDefinitionRegistrar
接口,接口中的registerBeanDefinitions
方法会传入AnnotationMetadata
注解信息以及BeanDefinitionRegistry
Bean的注册器。
Spring容器会在AbstractApplicationContext
的refresh
方法中通过调用invokeBeanFactoryPostProcessors(beanFactory)
方法,最终调用到实现了ImportBeanDefinitionRegistrar
接口的类中重写的方法。这里不过多说明,比较是讲AOP的~其调用链路如下(只有关键步骤,其他shen省略):
AbstractApplicationContext#refresh
AbstractApplicationContext#invokeBeanFactoryPostProcessors
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors
ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
ConfigurationClassPostProcessor#processConfigBeanDefinitions
ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars
ImportBeanDefinitionRegistrar#registerBeanDefinitions
2.2.2 AspectJAutoProxyRegistrar本身逻辑
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
可以看到最终调用到了AopConfigUtils#registerOrEscalateApcAsRequired
并传递了AnnotationAwareAspectJAutoProxyCreator
这么一个类型的参数,并最终吧AnnotationAwareAspectJAutoProxyCreator
注册到了Spring容器中。
2.3 AnnotationAwareAspectJAutoProxyCreator
既然向Spring容器中注入了AnnotationAwareAspectJAutoProxyCreator
,那就来看看吧~ 首先来张结构体系图:
2.3.1 笔者寻找关键代码的一些经过
从图中可以看出AnnotationAwareAspectJAutoProxyCreator
间接地实现了一些接口,其中几个比较重要的接口分别是BeanClassLoaderAware
、SmartInstantiationAwareBeanPostProcessor
、InstantiationAwareBeanPostProcessor
、BeanPostProcessor
其中BeanClassLoaderAware
的作用是获取类加载器,
SmartInstantiationAwareBeanPostProcessor
暂不讨论~
InstantiationAwareBeanPostProcessor
可以在Bean创建时尝试创建一个新的Bean,在AOP中的实现就是尝试创建一个代理类
BeanPostProcessor
的作用就是在bean创建前和创建后做一些操作
经过笔者的一番查找,在AbstractAutoProxyCreator
类中发现了两个重要的方法:
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
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;
}
}
.
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;
}
--------------------分割线--------------------
@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;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
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;
}
其中postProcessBeforeInstantiation
和postProcessAfterInitialization
方法中都有Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass());
但是在postProcessBeforeInstantiation方法中,由于TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
获取到的TargetSource
为空,因为其内部的判断if (this.customTargetSourceCreators != null && this.beanFactory != null && this.beanFactory.containsBean(beanName))
中customTargetSourceCreators
为空,所以并不是在此处创建代理对象,而是在postProcessAfterInitialization
中创建的代理对象
2.3.2 创建代理对象过程
直接看代码里面的注释吧...敲字好难敲~
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;
}
//这里是获取bean上面标注的注解信息,如@befor,@After等,并封装成Advisor对象
//这里面会获得可用的Advisor,并排序,所以才会现有befor,后有after
//Object[] specificInterceptors本质上是Advisor数组
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;
}
--------------------分割线------------------
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);
}
// 创建proxy工程
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 绑定Advisor与bean的关系
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 给工厂设置一些属性
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 创建代理
return proxyFactory.getProxy(getProxyClassLoader());
}
--------------------分割线------------------
public Object getProxy(@Nullable ClassLoader classLoader) {
// createAopProxy()是选择JDK还是CGLIB
// 这里我们看CGLIB的getProxy
return createAopProxy().getProxy(classLoader);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (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);
}
}
/**
* 老实说看不懂,反正就是创建一个代理对象了吧~
*/
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure 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 ClassLoaderAwareUndeclaredThrowableStrategy(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);
// Generate the proxy class and create a proxy instance.
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);
}
}
2.3.3 代理对象如何执行前置、后置等方法
将代理对象保存至容器。执行目标方法时:会调用CglibAopProxy.DynamicAdvisedInterceptor#intercept
方法
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 找到需要执行的Advisor数组
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
//真正调用方法的地方:proceed()方法
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
public Object proceed() throws Throwable {
//interceptorsAndDynamicMethodMatchers 其实就是Advisor数组,这里是如果当前执行的Advisor已经到了最后一个,就停止递归
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
return proceed();
}
}
else {
// 真正的befor、after等方法。这里在下面截取Demo对应的代码
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
-------------分割线-----------
MethodBeforeAdviceInterceptor类的(@Befor):
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
AspectJAfterAdvice类的(@After):
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
AfterReturningAdviceInterceptor类的:(@AfterReturning):
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
从上面的调用关系也可以看出来,是先执行到befor,再after,再本身的方法,再AfterReturning
3 写完了
写的不好,别建议,很多细节没写~不过大致流程就是这样啦~