说明:主要分成四部分,
- demo
- 后置处理器放入与调用时机(ioc中流程)
- 解析切面
- 怎么进行代理
- 怎么对增强进行排序
1 demo
1.1 pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.9</version>
</dependency>
1.2 配置类
package spring.kewen.ding.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan(basePackages = "spring.kewen.ding.bean")
@EnableAspectJAutoProxy
public class DingConfig {
}
1.3 切面
package spring.kewen.ding.bean.aop;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class DingAspect {
@Pointcut("execution(* spring.kewen.ding.bean.aop.*.*(..))")
public void pointCut(){};
@Before("pointCut()")
public void before(){
System.out.println("前置增强");
}
@After("pointCut()")
public void after(){
System.out.println("after");
}
}
1.4 bean
package spring.kewen.ding.bean.aop;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void print() {
System.out.println("userService方法");
}
}
1.5 启动类测试类
package spring.kewen.ding;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import spring.kewen.ding.bean.aop.UserService;
import spring.kewen.ding.config.DingConfig;
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext acac = new AnnotationConfigApplicationContext(DingConfig.class);
acac.getBean(UserService.class).print();
acac.close();
}
}
2 后置处理器放入与调用时机(ioc中流程)
2.1 第一阶段 将 AnnotationAwareAspectJAutoProxyCreator 转换成beandefinition,注册到容器
@EnableAspectJAutoProxy 注解开始,
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
2.2 第二阶段将将beandefinition注册到单例池(ioc)
// ioc中这一步
registerBeanPostProcessors(beanFactory);
2.3 什么时候进行代理
// 初始化后,执行 BeanPostProcessor#postProcessAfterInitialization
3 解析切面
说明:解析时机为创建我们自定义的第一个对象的时候,调用的 AbstractAutoProxyCreator#postProcessBeforeInstantiation 方法(InstantiationAwareBeanPostProcessor的实现类)
// 调用链路
/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractBeanFactory#createBean
/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation
/*
AbstractAutoProxyCreator (这里以及以上都是创建对象前调用的后置处理器,如果这里有返回对象,则后面创建对象的流程都不会走,直接返回这里创建的对象)
*/
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
/*
AspectJAwareAdvisorAutoProxyCreator,从这个方法后,就是解析@Aspect注解以及@Before等,后面多些的几个方法栈,主要是没有什么功能
*/
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#shouldSkip
/*
AnnotationAwareAspectJAutoProxyCreator
*/
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findCandidateAdvisors
/*
BeanFactoryAspectJAdvisorsBuilder
*/
org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors
/*
BeanFactoryAspectJAdvisorsBuilder
*/
org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors
重点在于这一行:List classAdvisors = this.advisorFactory.getAdvisors(factory);
流程大致是:
- 找到@Aspect修饰的class,
- 然后循环字段和方法
- 解析pointcut
- 组装成InstantiationModelAwarePointcutAdvisorImpl
- 缓存起来
4 怎么进行代理
4.1 确定代理方式(jdk和cglib,简单来说,就是如果是面向接口编程就是jdk,否则就是cglib)
// 调用链路
/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractBeanFactory#createBean
/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
/*
AbstractAutowireCapableBeanFactory
*/
initializeBean:1790, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
/*
AbstractAutoProxyCreator
*/
org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization
/*
AbstractAutoProxyCreator
*/
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
/*
AbstractAutoProxyCreator
*/
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
/*
ProxyFactory
proxyFactory.getProxy(classLoader)
*/
org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)
/*
ProxyCreatorSupport
*/
org.springframework.aop.framework.ProxyCreatorSupport#createAopProxy
/*
DefaultAopProxyFactory
*/
org.springframework.aop.framework.AopProxyFactory#createAopProxy
// 重要代码
@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);
}
}
// 每个判断条件的说明
- NativeDetector.inNativeImage()
判断环境(System.Property)中这个org.graalvm.nativeimage.imagecode是否有值。此环境是否存在于本机映像中) - config.isOptimize()
表示是否开启了优化策略,这个默认为false - config.isProxyTargetClass()
如果这个属性为true的话,就代表是需要基于类进行代理的,说白了就是使用cglib代理的意思,而如果为false的话,那么就代表基于接口代理,也就是使用jdk代理。 - hasNoUserSuppliedProxyInterfaces(config)
简单来说,要不就是目标类没有实现接口 ,要不就是目标类实现了接口且接口类型是SpringProxy,这两种情况只要满足一种就会返回true
- | jdk | cglib |
---|---|---|
NativeDetector.inNativeImage() | false | false |
config.isOptimize() | false | false |
config.isProxyTargetClass() | false | true |
hasNoUserSuppliedProxyInterfaces(config) | false | true |
另:cglib的时候,targetClass.isInterface()直接就是false,排除jdk动态代理
4.2 cglib动态代理生成
@Override
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 (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
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 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);
// 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);
}
}
4.3 jdk动态代理生成
重要的类:org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
invok方法
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
5 怎么对增强进行排序
5.1 排序的规则
- 首先定制规则的地方
位置就在注册 AnnotationAwareAspectJAutoProxyCreator(aop后置处理器,属于BeanPostProcessor的实现类)的时候,在BeanFactoryAware#setBeanFactory 过程中会创建InstanceComparator对象,这这对象就是用来实现Compare的重要功能 - 调用链路
/*
AbstractAutowireCapableBeanFactory
create AnnotationAwareAspectJAutoProxyCreator
*/
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
/*
AbstractAdvisorAutoProxyCreator
*/
org.springframework.beans.factory.BeanFactoryAware#setBeanFactory
/*
AnnotationAwareAspectJAutoProxyCreator
*/
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#initBeanFactory
/*
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory)
ReflectiveAspectJAdvisorFactory 静态代码块
静态代码块内容
Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
new InstanceComparator<>(
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
(Converter<Method, Annotation>) method -> {
AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
return (ann != null ? ann.getAnnotation() : null);
});
*/
org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory
/*
构造方法
InstanceComparator
*/
org.springframework.util.comparator.InstanceComparator#InstanceComparator
- 重要代码
// 构造方法
public InstanceComparator(Class<?>... instanceOrder) {
Assert.notNull(instanceOrder, "'instanceOrder' array must not be null");
this.instanceOrder = instanceOrder;
}
/*
说明:
instanceOrder 就是 org.aspectj.lang.annotation.Around 等class对象数组,顺序是:
0 = {Class@1706} "interface org.aspectj.lang.annotation.Around"
1 = {Class@1322} "interface org.aspectj.lang.annotation.Before"
2 = {Class@1321} "interface org.aspectj.lang.annotation.After"
3 = {Class@1707} "interface org.aspectj.lang.annotation.AfterReturning"
4 = {Class@1708} "interface org.aspectj.lang.annotation.AfterThrowing"
*/
// org.springframework.util.comparator.InstanceComparator#getOrder
private int getOrder(@Nullable T object) {
if (object != null) {
for (int i = 0; i < this.instanceOrder.length; i++) {
if (this.instanceOrder[i].isInstance(object)) {
return i;
}
}
}
return this.instanceOrder.length;
}
/*
由此可见,排序规则就是
1).首先 创建 InstanceComparator 并初始化一个class数组,数组中元素的顺序是:Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
2).排序需要能比较的字段,或者规则,这个就是 某种增强在这个数组中下标的位置,如果是一个不存在的增强,直接返回数组长度
*/
5.2 排序的位置
排序的位置就在解析Aspect注解和@Before等注解的时候。
我们上面已经说明,解析注解一个重要点就是 List classAdvisors = this.advisorFactory.getAdvisors(factory);。
在这个方法中会拿到到所有家了增强注解的方法,这其中就进行了排序(List是有序的)
重点代码(debug方式进入的,不重要的进行跳过了):
- getAdvisors方法中有一个实现
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
- getAdvisorMethods(aspectClass))
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter);
if (methods.size() > 1) {
methods.sort(adviceMethodComparator);
}
return methods;
}
- methods.sort(adviceMethodComparator);
@Override
public int compare(T o1, T o2) {
int i1 = getOrder(o1);// 看到getOrder就差不多了
int i2 = getOrder(o2);
return (Integer.compare(i1, i2));
}
// 执行代理方法的时候,怎么执行,待续(责任链模式)