测试项目已上传到码云,可以下载:https://gitee.com/yangxioahui/aopdemo.git

具体如下:

public interface Calc {
Integer add(int num1,int num2);
}
//目标是对add 方法进行切入
@Component
public class MyMath implements Calc { public Integer add(int num1,int num2){
return num1+num2;
} }
@Aspect
@Component
public class MyAspectJ {
@Pointcut(" execution(* com.yang.xiao.hui.aop.MyMath.*(..))")
private void pointcut(){}
@Before(value = "pointcut()")
public void before(JoinPoint joinPoint){
System.out.println("before。。。。。");
}
@After(value = "pointcut()")
public void after(JoinPoint joinPoint){
System.out.println("after。。。。");
} @AfterReturning(value = "pointcut()")
public void afterReturning(){
System.out.println("afterReturning。。。");
} @AfterThrowing(value = "pointcut()")
public void afterThrowing(JoinPoint joinPoint){
System.out.println("afterThrowing。。。。");
} @Around(value ="pointcut()")
public void around(ProceedingJoinPoint joinPoint){
System.out.println("around-before。。。。");
try {
Object proceed = joinPoint.proceed();
System.out.println("around-after_return。。。");
} catch (Throwable throwable) {
System.out.println("around-throw。。。"+throwable.getMessage());
}
System.out.println("around-after。。。");
}
} //测试类
@Configuration
@ComponentScan("com.yang.xiao.hui.aop")
@EnableAspectJAutoProxy(exposeProxy = true)
public class App
{
public static void main( String[] args )
{ ApplicationContext ctx = new AnnotationConfigApplicationContext(App.class);
Calc myMath = (Calc)ctx.getBean("myMath");
myMath.add(3,5);
System.out.println(ctx.getBean("myMath").getClass()); }
}

启动项目结果:

至此,测试环境搭建完毕

原理分析:
我们要对MyMath 类的add 方法进行前后代理,我们也可以自己实现:

我们实现的叫静态代理,如果是程序实现的叫动态代理;切入的方式有前置切入,后置切入等,切入点有切入表达式(Pointcut),在java中,一切皆对象,spring将各种切入方式叫做Advice(增强器),如BeforeAdvice,而我们是通过方法切入

所以又叫MethodBeforeAdvice:

单有一个Advice 我们并不知道要给哪个类进行切入,因此还需要切入点,于是我们将Advice和切入点Pointcut 结合一起组成一个Advisor:

例如:DefaultPointcutAdvisor它的构造器:

一个被切入的类,它的代理类,会有很多个Advisor,那么我们称这个代理类叫做Advised:

至此,我们知道了advice ,advisor 和advised的三者之间的关系了:
下面的我们要解决的问题是:1.各种切入方式是如何被封装成advisor的 2 如何知道某个类是否需要被代理 3. 如何创建代理类 4 类被代理后,目标方法是如何执行的:

先来看一个注解:@EnableAspectJAutoProxy()


点击进入该注解:

我们继续跟进,看看到底向容器注册的是哪个bean;

我们再看看注解信息是怎么保存到注册器中的;

小结:@EnableAspectJAutoProxy 注解最终向容器中注入了一个 bean---- AnnotationAwareAspectJAutoProxyCreator,因此我们问题的答案都可以在这个bean找到,那么我们看看其继承体系:


可见,AnnotationAwareAspectJAutoProxyCreator是一个beanPostProcessor,也就是后置处理器,会在bean的不同生命周期里其作用:

因此,这些生命周期里,会进行代理对象的创建:

我们debug 调试容器创建过程:

省略n步骤:

public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames; //首次进来,这个为null if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false); //容器中获取所有的beanName,因为Object可以代表所有的类型
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) { //isEligibleBean(beanName)这个基本返回true
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
Class<?> beanType = this.beanFactory.getType(beanName); //获取对应的类型
if (beanType == null) {
continue;
}
if (this.advisorFactory.isAspect(beanType)) { //判断类有没@Aspect注解,而我们定义的MyAspectJ是有该注解的
aspectNames.add(beanName);//切面类可能有多个,我本次测试写了一个MyAspectJ
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { //如果我们的MyMyAspectJ是单例的话,条件成立,显然,我们的就是单例
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); //获取一个切面工厂
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);//这里获取了我们要的advisor,所以稍后要分析
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors); //如果是单例就缓存起来,下次就不用再次获取了
}
else {
this.aspectFactoryCache.put(beanName, factory);//非单例就缓存工厂
}
advisors.addAll(classAdvisors);//收集所有的advisor
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors; //第一次进来在这里就返回去了,下面的不会执行
}
}
}
     第二次进来,从缓存中取 
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors); //单例的切面类,从缓存中就可以取到他们所有的advisor
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory)); //非单例的切面类,从工厂中去处
}
}
return advisors;
}

//通过上面分析:最终会通过调用advisorFactory.getAdvisors(factory)获取到advisor,继续跟进:

@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); //获取切面类,在这里就是我们的com.yang.xiao.hui.aop.MyAspectJ
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();//获取类名,这里是myAspectJ
validate(aspectClass);//这里主要校验切面类的父类有没@Aspect注解,如果有,必须是抽象类,其次会校验切面类有没@Aspect注解 // 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<>();
for (Method method : getAdvisorMethods(aspectClass)) { //通过切面类,获取所有的方法,方法不包含含有@Pointcut注解的方法,因为带有该注解的方法为切入点
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); //这里将方法封装成了Advisor,后续会跟踪
if (advisor != null) { //并不是所有方法,都能封装成advisor的,只有含有@before,@after等注解的方法才会被封装
advisors.add(advisor);
}
} // If it's a per target aspect, emit the dummy instantiating aspect.
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { //懒加载相关的,会增加一个advisor,显然我们的不是
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
} // Find introduction fields.
for (Field field : aspectClass.getDeclaredFields()) { //查询有没哪个字段是有@DeclareParents注解的,我们定义的类没有字段
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
} return advisors;
}

根据上面分析,切面类的方法最终转成advisor,是调用了 Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);我们跟进去:

@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) { validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); //校验切面类的父类有没@Aspect注解,如果有,必须是抽象类,其次会校验切面类有没@Aspect注解 AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); //里面会校验candidateAdviceMethod方法是否有@Before @After等注解
if (expressionPointcut == null) {
return null;
} return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName); //这个就是我们要找的advisor,expressionPointcut含有pointcut和advice
 
}

我们分析下: AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); 方法:

@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()); //这里将@before/@After等注解的切入点表达式存起来了
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}

@Nullable
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) { //查询某个方法是否有aspectj相关注解
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) { //ASPECTJ_ANNOTATION_CLASSES //相关注解类如下图:
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}

//经过分析,所有的advisor,最终的类型是InstantiationModelAwarePointcutAdvisorImpl 看看起构造器

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { this.declaredPointcut = declaredPointcut; //切入点表达式
this.declaringClass = aspectJAdviceMethod.getDeclaringClass(); //增强方法所在的类,也就是切入类
this.methodName = aspectJAdviceMethod.getName(); //增强的方法名@before等注解标注的类
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();//advice方法的参数类型
this.aspectJAdviceMethod = aspectJAdviceMethod;//advice方法,@before等注解标注的方法
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);//创建一个advice
}
}

我们看看advice的创建过程:

private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
@Override
@Nullable
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);//校验增强方法是否含有@before等相关注解
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)) { //这里又一次校验有没@Aspect注解
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()) { //根据注解的类型创建对应的advice
case AtPointcut: //如果是切入点,其实就不用创建advice了
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
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;
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;
}

通过advice的创建过程,我们知道,一个advice主要包含增强的方法,方法参数,以及切入点,而advisor是包含Advice的,并且属性更多,功能更强大

 

至此,我们的第一个问题解决了:各种切入方式是如何被封装成advisor的?

小结:AnnotationAwareAspectJAutoProxyCreator这个类实现了InstantiationAwareBeanPostProcessor接口,所以其中有个方法:Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)

在其他bean创建的过程中,会调用该方法,该方法会去查找容器中所有的advisor,查找的思路是获取所有的Bean的名称,然后通过名称获取bean的类型(此时bean还没实例化,所以取得是类型),之后判断有没@Aspect注解如果有该注解的话,就判断类下面的方法有没Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class 这几个注解,有就将对应的方法封装成advice,进一步封装成advisor

至此,所有的切入方法都封装成了advisor,存到了一个list集合中,下面分析代理类的创建,也就是我们的MyMath被代理过程:debug调试其创建bean的过程

前面分析过: AnnotationAwareAspectJAutoProxyCreator 实现BeanPostProcessor接口,该接口有2个方法:

我们先看看postProcessBeforeInitialization 的代码:

可见,没做任何逻辑,我们再看看另外一个方法:postProcessAfterInitialization

所以我们断点在该方法,调试MyMath创建过程:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { //在postProcessBeforeInstantiation方法也有创建代理对象逻辑,如果在那个方法创建的代理对象会存到targetSourcedBeans
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { //advisedBeans 缓存中已经有该bean,并且不用增强
return bean;
}
//InfrastructureClass 是指Advice,Pointcut,Advisor,AopInfrastructureBean; shouldSkip(bean.getClass(), beanName)指的是beanName以 “.ORIGINAL” 结尾的
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { 在postProcessBeforeInstantiation这个方法也有一样的逻辑
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
} // Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); //获取能用在该类上的advisor,逻辑是根据切面表达式来判断,之后会分析
if (specificInterceptors != DO_NOT_PROXY) { //如果获取到的advisor不为空,也就是由advisor可以用在该类上就创建代理对象
this.advisedBeans.put(cacheKey, Boolean.TRUE); //设置缓存,说明该bean的创建需要代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); //创建代理对象
this.proxyTypes.put(cacheKey, proxy.getClass());//缓存代理对象的类
return proxy;
} this.advisedBeans.put(cacheKey, Boolean.FALSE); //如果没有可用的增强器,就标注上该bean不用创建代理
return bean;
}

//上面要关注的2个方法,一个是如何查找一个类的增强器,也就是advisor,第二个是代理对象的创建:

先看这个方法:Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors(); //获取所有的advisor,这个在之前已经分析过了
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);//拿到所有的advisor,看看哪些能用在指定的bean,下面会跟进分析
extendAdvisors(eligibleAdvisors); //而外加入了一个advisor: advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors); //排序
}
return eligibleAdvisors;
}
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); //继续跟进该方法
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
    public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) { //如果没有候选的advisor,就不用走下去了
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {//前面分析过,我们的advisor类型是:InstantiationModelAwarePointcutAdvisor 所以不会进入下面逻辑
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {//前面分析过,我们的advisor类型是:InstantiationModelAwarePointcutAdvisor 所以不会进入下面逻辑
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) { //最终会到达这里,所以canApply(candidate, clazz, hasIntroductions) 决定了该advisor能否用于指定的class
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions); //判断逻辑会到达这里
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) { //判断切入点过滤的类型能否跟指定的类匹配,例如切入点表达式指定的是A类型,那么只有A类型才符合
return false;
} MethodMatcher methodMatcher = pc.getMethodMatcher(); //判断切入的方法是否符合,因为并非所有的方法都需要被切入
if (methodMatcher == MethodMatcher.TRUE) { //对于用*表示的匹配模式,所有方法都会被匹配
// No need to iterate the methods if we're matching any method anyway...
return true;
} IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
} Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) { //如果目标class不是Proxy的子类
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); //获取所有的父接口 for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); //获取所有的方法
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true; //判断是否有方法匹配了,只要有一个方法匹配上切入点表达式,对应的advisor就可以用在目标class上
}
}
} return false;
}

至此,我们知道了给目标class获取advisor的原理: 获取所有的advisor,然后遍历,根据advisor的切入点表达式Pointcut,校验目标class的方法是否有匹配上advisor的

接着,我们分析代理对象的创建过程:

Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); //创建代理对象
目标bean被封装成了一个SingletonTargetSource
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
       //这里给bean的定义设置了一个属性originalTargetClass 
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
} ProxyFactory proxyFactory = new ProxyFactory();//代理工厂
proxyFactory.copyFrom(this); if (!proxyFactory.isProxyTargetClass()) { //@EnableAspectJAutoProxy 注解的proxyTargetClass属性,当为true时,就不支持jdk动态代理,全部使用cglib,默认是false
if (shouldProxyTargetClass(beanClass, beanName)) { //判断bean的定义对象的属性preserveTargetClass 是否为true,为true时,只支持cglib
proxyFactory.setProxyTargetClass(true);
}
else {
//判断beanClass所有的实现接口,排除InitializingBean,AutoCloseable,DisposableBean,Closeable,Aware,是否还有其他接口,是的话,就可以用jdk动态代理
evaluateProxyInterfaces(beanClass, proxyFactory);
}
} Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);//主要的功能是强转,因为specificInterceptors数组的类型是Object
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);//目前空实现 proxyFactory.setFrozen(this.freezeProxy); //设置是否需要冻结代理相关的配置,false
if (advisorsPreFiltered()) { //advisor是否是过滤过的了,根据前面分析,advisor用于指定的bean前,通过切入点表达式过滤过了
proxyFactory.setPreFiltered(true);
} return proxyFactory.getProxy(getProxyClassLoader());
}

//上面只是为需要代理的bean,创建了一个代理工厂,并且代理工厂设置了advisors 和目标bean对象,接下来跟进代理对象创建:

先分析: createAopProxy()

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
//前面ProxyFactory 设置的目标对象,advisors 都存在AdvisedSupport这里了
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
     // 源码对 config.isOptimize()解释:optimization will usually mean that advice changes won't take effect after a proxy has been created.
//config.isOptimize()默认是false,config.isProxyTargetClass这个是@EnableAspectJAutoProxy的属性,为true时,即使目标类实现了接口也用cglib代理
//hasNoUserSuppliedProxyInterfaces(config) 没有用户提供的接口时,也没法使用jdk动态代理
 
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)) { //如果目标类就是接口,或者其继承了Proxy类,那就没法使用cglib代理了
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config); //使用cglib代理
}
else {
return new JdkDynamicAopProxy(config); //使用jdk代理
}
}
... 省略其他代码
}

由于我的是jdk动态代理,执行getProxy后:

我们看看获取接口的方法:

static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) { //主要是加上了三个接口SpringProxy,Advised,DecoratingProxy
Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
if (specifiedInterfaces.length == 0) {
// No user-specified interfaces: check whether target class is an interface.
Class<?> targetClass = advised.getTargetClass();
if (targetClass != null) {
if (targetClass.isInterface()) {
advised.setInterfaces(targetClass);
}
else if (Proxy.isProxyClass(targetClass)) {
advised.setInterfaces(targetClass.getInterfaces());
}
specifiedInterfaces = advised.getProxiedInterfaces();
}
}
boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
int nonUserIfcCount = 0;
if (addSpringProxy) {
nonUserIfcCount++;
}
if (addAdvised) {
nonUserIfcCount++;
}
if (addDecoratingProxy) {
nonUserIfcCount++;
}
Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];
System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
int index = specifiedInterfaces.length;
if (addSpringProxy) {
proxiedInterfaces[index] = SpringProxy.class;
index++;
}
if (addAdvised) {
proxiedInterfaces[index] = Advised.class;
index++;
}
if (addDecoratingProxy) {
proxiedInterfaces[index] = DecoratingProxy.class;
}
return proxiedInterfaces;
}
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); 这个是jdk源码的内容了

至此,spring创建代理对象的源码分析完毕了,我们看看cglib的getProxy方法:

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
} try {
Class<?> rootClass = this.advised.getTargetClass(); //因为cglib使用的继承方式,所以目标类就是父类
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) { //判断目标类是否已经是cglib的代理类了,cglib的代理类,beanName是以"$$" 结尾的
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(); //cglib的创建器,相当于jdk动态代理的代理工厂Proxy
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)); //跟jdk代理一样,这里也会新增三个接口SpringProxy,Advised,DecoratingProxy
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);//cglib代理对象的命名策略,会加上"$$" 和 BySpringCGLIB 这些字符
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);
}
}
@Override
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
Class<?> proxyClass = enhancer.createClass(); //创建出代理类
Object proxyInstance = null; if (objenesis.isWorthTrying()) {
try {
proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache()); //创建代理实例
}
catch (Throwable ex) {
logger.debug("Unable to instantiate proxy using Objenesis, " +
"falling back to regular proxy construction", ex);
}
} if (proxyInstance == null) {
// Regular instantiation via default constructor...
try {
Constructor<?> ctor = (this.constructorArgs != null ?
proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
proxyClass.getDeclaredConstructor());
ReflectionUtils.makeAccessible(ctor);
proxyInstance = (this.constructorArgs != null ?
ctor.newInstance(this.constructorArgs) : ctor.newInstance()); //通过构造器创建代理实例
}
catch (Throwable ex) {
throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
"and regular proxy instantiation via default constructor fails as well", ex);
}
} ((Factory) proxyInstance).setCallbacks(callbacks);
return proxyInstance;
}

我们可以输出代理类的字节码,设置一个属性:System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles","true");

执行后,在类路径可以看到:

找到我们的目标类:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// package com.sun.proxy; import com.yang.xiao.hui.aop.Calc;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.core.DecoratingProxy;
//代理对象的所有方法的调用最终都会交给InvocationHandler 的invoke方法执行
public final class $Proxy22 extends Proxy implements Calc, SpringProxy, Advised, DecoratingProxy { // SpringProxy, Advised, DecoratingProxy 这三个接口是后面加上的,前面分析过了
private static Method m1;
private static Method m9;
private static Method m14;
private static Method m13;
private static Method m19;
private static Method m24;
private static Method m4;
private static Method m8;
private static Method m17;
private static Method m18;
private static Method m0;
private static Method m23;
private static Method m16;
private static Method m11;
private static Method m7;
private static Method m2;
private static Method m26;
private static Method m15;
private static Method m27;
private static Method m20;
private static Method m5;
private static Method m6;
private static Method m21;
private static Method m10;
private static Method m3;
private static Method m25;
private static Method m12;
private static Method m22; public $Proxy22(InvocationHandler var1) throws {
super(var1);
} public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final boolean isExposeProxy() throws {
try {
return (Boolean)super.h.invoke(this, m9, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final void addAdvisor(Advisor var1) throws AopConfigException {
try {
super.h.invoke(this, m14, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final boolean isProxyTargetClass() throws {
try {
return (Boolean)super.h.invoke(this, m13, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final void removeAdvisor(int var1) throws AopConfigException {
try {
super.h.invoke(this, m19, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final Class[] getProxiedInterfaces() throws {
try {
return (Class[])super.h.invoke(this, m24, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final int indexOf(Advisor var1) throws {
try {
return (Integer)super.h.invoke(this, m4, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final TargetSource getTargetSource() throws {
try {
return (TargetSource)super.h.invoke(this, m8, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final void addAdvice(int var1, Advice var2) throws AopConfigException {
try {
super.h.invoke(this, m17, new Object[]{var1, var2});
} catch (RuntimeException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
} public final void addAdvice(Advice var1) throws AopConfigException {
try {
super.h.invoke(this, m18, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final boolean isInterfaceProxied(Class var1) throws {
try {
return (Boolean)super.h.invoke(this, m23, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final boolean removeAdvice(Advice var1) throws {
try {
return (Boolean)super.h.invoke(this, m16, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final void setExposeProxy(boolean var1) throws {
try {
super.h.invoke(this, m11, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final void setTargetSource(TargetSource var1) throws {
try {
super.h.invoke(this, m7, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final Class getTargetClass() throws {
try {
return (Class)super.h.invoke(this, m26, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final void addAdvisor(int var1, Advisor var2) throws AopConfigException {
try {
super.h.invoke(this, m15, new Object[]{var1, var2});
} catch (RuntimeException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
} public final Class getDecoratedClass() throws {
try {
return (Class)super.h.invoke(this, m27, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final boolean removeAdvisor(Advisor var1) throws {
try {
return (Boolean)super.h.invoke(this, m20, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final int indexOf(Advice var1) throws {
try {
return (Integer)super.h.invoke(this, m5, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final boolean isFrozen() throws {
try {
return (Boolean)super.h.invoke(this, m6, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final boolean replaceAdvisor(Advisor var1, Advisor var2) throws AopConfigException {
try {
return (Boolean)super.h.invoke(this, m21, new Object[]{var1, var2});
} catch (RuntimeException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
} public final void setPreFiltered(boolean var1) throws {
try {
super.h.invoke(this, m10, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final Integer add(int var1, int var2) throws {
try {
return (Integer)super.h.invoke(this, m3, new Object[]{var1, var2});
} catch (RuntimeException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
} public final String toProxyConfigString() throws {
try {
return (String)super.h.invoke(this, m25, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final Advisor[] getAdvisors() throws {
try {
return (Advisor[])super.h.invoke(this, m12, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final boolean isPreFiltered() throws {
try {
return (Boolean)super.h.invoke(this, m22, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m9 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isExposeProxy");
m14 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvisor", Class.forName("org.springframework.aop.Advisor"));
m13 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isProxyTargetClass");
m19 = Class.forName("org.springframework.aop.framework.Advised").getMethod("removeAdvisor", Integer.TYPE);
m24 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getProxiedInterfaces");
m4 = Class.forName("org.springframework.aop.framework.Advised").getMethod("indexOf", Class.forName("org.springframework.aop.Advisor"));
m8 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getTargetSource");
m17 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvice", Integer.TYPE, Class.forName("org.aopalliance.aop.Advice"));
m18 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvice", Class.forName("org.aopalliance.aop.Advice"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m23 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isInterfaceProxied", Class.forName("java.lang.Class"));
m16 = Class.forName("org.springframework.aop.framework.Advised").getMethod("removeAdvice", Class.forName("org.aopalliance.aop.Advice"));
m11 = Class.forName("org.springframework.aop.framework.Advised").getMethod("setExposeProxy", Boolean.TYPE);
m7 = Class.forName("org.springframework.aop.framework.Advised").getMethod("setTargetSource", Class.forName("org.springframework.aop.TargetSource"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m26 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getTargetClass");
m15 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvisor", Integer.TYPE, Class.forName("org.springframework.aop.Advisor"));
m27 = Class.forName("org.springframework.core.DecoratingProxy").getMethod("getDecoratedClass");
m20 = Class.forName("org.springframework.aop.framework.Advised").getMethod("removeAdvisor", Class.forName("org.springframework.aop.Advisor"));
m5 = Class.forName("org.springframework.aop.framework.Advised").getMethod("indexOf", Class.forName("org.aopalliance.aop.Advice"));
m6 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isFrozen");
m21 = Class.forName("org.springframework.aop.framework.Advised").getMethod("replaceAdvisor", Class.forName("org.springframework.aop.Advisor"), Class.forName("org.springframework.aop.Advisor"));
m10 = Class.forName("org.springframework.aop.framework.Advised").getMethod("setPreFiltered", Boolean.TYPE);
m3 = Class.forName("com.yang.xiao.hui.aop.Calc").getMethod("add", Integer.TYPE, Integer.TYPE);
m25 = Class.forName("org.springframework.aop.framework.Advised").getMethod("toProxyConfigString");
m12 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getAdvisors");
m22 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isPreFiltered");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}

//通过分析,我们知道,jdk动态代理类的所有方法,都会交给//代理对象的所有方法的调用最终都会交给InvocationHandler 的invoke方法执行,那么这个InvocationHandler 又是哪里来的呢,我们回到jdk动态代理创建过程:

因此代理类的方法会被JdkDynamicAopProxy 的invoke 拦截,而JdkDynamicAopProxy有个属性:AdvisedSupport 该对象拥有被代理对象和advisors,因此可以进行前后拦截了,而AdvisedSupport 是什么时候传入的呢?

至此,哪个类会被代理,以及如何代理,分析完毕,下篇博客,我们会分析,代理方法的执行流程

 
 

												

sping aop 源码分析(-)-- 代理对象的创建过程分析的更多相关文章

  1. Spring AOP源码分析--代理方式的选择

    能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! 年前写了一个面试突击系列的文章,目前只有redis相关的.在这个系列里,我整理了一些面试题与大家 ...

  2. Spring AOP源码分析(三)创建AOP代理

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.获取增强器 1. 普通增强器的获取 2. 增加同步实例化增强 ...

  3. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  4. Spring AOP源码分析(三):基于JDK动态代理和CGLIB创建代理对象的实现原理

    AOP代理对象的创建 AOP相关的代理对象的创建主要在applyBeanPostProcessorsBeforeInstantiation方法实现: protected Object applyBea ...

  5. spring aop 源码分析(三) @Scope注解创建代理对象

    一.源码环境的搭建: @Component @Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON,proxyMode = ScopedP ...

  6. spring aop 源码分析(二) 代理方法的执行过程分析

    在上一篇aop源码分析时,我们已经分析了一个bean被代理的详细过程,参考:https://www.cnblogs.com/yangxiaohui227/p/13266014.html 本次主要是分析 ...

  7. spring AOP源码分析(三)

    在上一篇文章 spring AOP源码分析(二)中,我们已经知道如何生成一个代理对象了,那么当代理对象调用代理方法时,增强行为也就是拦截器是如何发挥作用的呢?接下来我们将介绍JDK动态代理和cglib ...

  8. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

  9. Spring AOP 源码分析 - 筛选合适的通知器

    1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...

随机推荐

  1. 速记OSI七层协议模型

    OSI七层协议模型 第一层:物理层(Physical) 第二层:数据链路层(Data-Link) 第三层:网络层(NetWork) 第四层:传输层(Transport) 第五层:会话层(Session ...

  2. Java面试题 200+

    面试题包含的内容了十九了模块:Java 基础.容器.多线程.反射.对象拷贝.Java Web 模块.异常.网络.设计模式.Spring/Spring MVC.Spring Boot/Spring Cl ...

  3. Flyway版本化管理数据库脚本

    假如我们有一个叫shiny的项目,它是由一个程序Shiny-Server 和一个数据库 Shiny-DB组成的; 简单结构图如下: 但是很多时候,现实开发团队是这样的: 我们的项目shiny项目的运行 ...

  4. 用aop去解决事物问题(tx)记录学习之aop1.2

    上一个文章我们了解了什么事aop,以及aop的使用方法,主要是把自己想要加入的通知(advice)加入到我们的方法里, 比如上一章我们说的事把myadvice类中的before方法织入到userser ...

  5. Selenium 如何复用浏览器【解决扫码登录等问题】

    Selenium中复用已经打开的浏览器进行自动化测试,可以辅助我们解决某些登录需要扫二维码之后,才能进行的操作 目前只支持谷歌Chrome浏览器,那需要做哪些准备操作呢?往下看 1.windows和M ...

  6. 1.异常页面: /File/ApplyFileForm.aspx 2.异常信息: 基类包括字段“PageOfficeCtrl1”,但其类型(PageOffice.PageOfficeCtrl)与控件(PageOffice.PageOfficeCtrl)的类型不兼容。

    出现页面报错的解决如下: 1.  在  .aspx  页面报错的字段  ID 名称更改: 2.  在没有重复 ID控件,先实行步骤1, 生成项目是ok的,然后,还原,原来的ID名称,再去浏览页面运行, ...

  7. TonWeb6.1Linux安装文档

    东方通部署文档   东方通安装部署文档 准备文件:开始安装:警告:在安装之前先安装JDK,JDK要求JDK5以上Linux安装:运行安装包sh Install_TW6.1.5.15_Standard_ ...

  8. Oracle的timestamp字段更新实验 结论:只有逐条更新才能保证timestamp字段有差别,批量更新只会得到一致的时间,此操作无关时间精度.

    有这么一张表: create table hy_testtime( id number(6,0) not null primary key, name nvarchar2(20) not null, ...

  9. 20190923-08Linux压缩和解压类 000 016

    gzip/gunzip 压缩 1.基本语法 gzip 文件 (功能描述:压缩文件,只能将文件压缩为*.gz文件) gunzip 文件.gz (功能描述:解压缩文件命令) 2.经验技巧 (1)只能压缩文 ...

  10. IDEA项目左侧目录看不到target

    点击如下图所示图标,然后选择Show Excluded Files后即可出现