Spring AOP源码学习:创建 AOP 代理

// 2.1 跳过当前正在创建的advisor

if (this.beanFactory.isCurrentlyInCreation(name)) {

if (logger.isDebugEnabled()) {

logger.debug(“Skipping currently created advisor '” + name + “'”);

}

} else {

try {

// 2.2 通过beanName获取对应的bean对象,并添加到advisors

advisors.add(this.beanFactory.getBean(name, Advisor.class));

} catch (BeanCreationException ex) {

Throwable rootCause = ex.getMostSpecificCause();

if (rootCause instanceof BeanCurrentlyInCreationException) {

BeanCreationException bce = (BeanCreationException) rootCause;

if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {

if (logger.isDebugEnabled()) {

logger.debug(“Skipping advisor '” + name +

"’ with dependency on currently created bean: " + ex.getMessage());

}

// Ignore: indicates a reference back to the bean we’re trying to advise.

// We want to find advisors other than the currently created bean itself.

continue;

}

}

throw ex;

}

}

}

}

// 3.返回符合条件的advisor列表

return advisors;

}

代码块6:buildAspectJAdvisors


public List buildAspectJAdvisors() {

List aspectNames = this.aspectBeanNames;

// 1.如果aspectNames为空,则进行解析

if (aspectNames == null) {

synchronized (this) {

aspectNames = this.aspectBeanNames;

if (aspectNames == null) {

List advisors = new LinkedList();

aspectNames = new LinkedList();

// 1.1 获取所有的beanName

String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(

this.beanFactory, Object.class, true, false);

// 1.2 循环遍历所有的beanName,找出对应的增强方法

for (String beanName : beanNames) {

// 1.3 不合法的beanName则跳过,默认返回true,子类可以覆盖实现,AnnotationAwareAspectJAutoProxyCreator

// 实现了自己的逻辑,支持使用includePatterns进行筛选

if (!isEligibleBean(beanName)) {

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.

// 获取beanName对应的bean的类型

Class<?> beanType = this.beanFactory.getType(beanName);

if (beanType == null) {

continue;

}

// 1.4 如果beanType存在Aspect注解则进行处理

if (this.advisorFactory.isAspect(beanType)) {

// 将存在Aspect注解的beanName添加到aspectNames列表

aspectNames.add(beanName);

// 新建切面元数据

AspectMetadata amd = new AspectMetadata(beanType, beanName);

// 获取per-clause的类型是SINGLETON

if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {

// 使用BeanFactory和beanName创建一个BeanFactoryAspectInstanceFactory,主要用来创建切面对象实例

MetadataAwareAspectInstanceFactory factory =

new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);

// 1.5 解析标记AspectJ注解中的增强方法

List classAdvisors = this.advisorFactory.getAdvisors(factory);

// 1.6 放到缓存中

if (this.beanFactory.isSingleton(beanName)) {

// 如果beanName是单例则直接将解析的增强方法放到缓存

this.advisorsCache.put(beanName, classAdvisors);

} else {

// 如果不是单例,则将factory放到缓存,之后可以通过factory来解析增强方法

this.aspectFactoryCache.put(beanName, factory);

}

// 1.7 将解析的增强器添加到advisors

advisors.addAll(classAdvisors);

} else {

// 如果per-clause的类型不是SINGLETON

// Per target or per this.

if (this.beanFactory.isSingleton(beanName)) {

// 名称为beanName的Bean是单例,但切面实例化模型不是单例,则抛异常

throw new IllegalArgumentException(“Bean with name '” + beanName +

“’ is a singleton, but aspect instantiation model is not singleton”);

}

MetadataAwareAspectInstanceFactory factory =

new PrototypeAspectInstanceFactory(this.beanFactory, beanName);

// 将factory放到缓存,之后可以通过factory来解析增强方法

this.aspectFactoryCache.put(beanName, factory);

// 解析标记AspectJ注解中的增强方法,并添加到advisors中

advisors.addAll(this.advisorFactory.getAdvisors(factory));

}

}

}

// 1.9 将解析出来的切面beanName放到缓存aspectBeanNames

this.aspectBeanNames = aspectNames;

// 1.10 最后返回解析出来的增强器

return advisors;

}

}

}

// 2.如果aspectNames不为null,则代表已经解析过了,则无需再次解析

// 2.1 如果aspectNames是空列表,则返回一个空列表。空列表也是解析过的,只要不是null都是解析过的。

if (aspectNames.isEmpty()) {

return Collections.emptyList();

}

// 2.2 aspectNames不是空列表,则遍历处理

List advisors = new LinkedList();

for (String aspectName : aspectNames) {

// 根据aspectName从缓存中获取增强器

List cachedAdvisors = this.advisorsCache.get(aspectName);

if (cachedAdvisors != null) {

// 根据上面的解析,可以知道advisorsCache存的是已经解析好的增强器,直接添加到结果即可

advisors.addAll(cachedAdvisors);

} else {

// 如果不存在于advisorsCache缓存,则代表存在于aspectFactoryCache中,

// 从aspectFactoryCache中拿到缓存的factory,然后解析出增强器,添加到结果中

MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);

advisors.addAll(this.advisorFactory.getAdvisors(factory));

}

}

// 返回增强器

return advisors;

}

1.5 解析标记 AspectJ 注解中的增强方法,见代码块7。

代码块7:getAdvisors


@Override

public List getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {

// 1.前面我们将beanClass和beanName封装成了aspectInstanceFactory的AspectMetadata属性,

// 这边可以通过AspectMetadata属性重新获取到当前处理的切面类

Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();

// 2.获取当前处理的切面类的名字

String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();

// 3.校验切面类

validate(aspectClass);

// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator

// so that it will only instantiate once.

// 4.使用装饰器包装MetadataAwareAspectInstanceFactory,以便它只实例化一次。

MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =

new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

List advisors = new LinkedList();

// 5.获取切面类中的方法(也就是我们用来进行逻辑增强的方法,被@Around、@After等注解修饰的方法,使用@Pointcut的方法不处理)

for (Method method : getAdvisorMethods(aspectClass)) {

// 6.处理method,获取增强器

Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);

if (advisor != null) {

// 7.如果增强器不为空,则添加到advisors

advisors.add(advisor);

}

}

// If it’s a per target aspect, emit the dummy instantiating aspect.

if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {

// 8.如果寻找的增强器不为空而且又配置了增强延迟初始化,那么需要在首位加入同步实例化增强器(用以保证增强使用之前的实例化)

Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);

advisors.add(0, instantiationAdvisor);

}

// Find introduction fields.

// 9.获取DeclareParents注解

for (Field field : aspectClass.getDeclaredFields()) {

Advisor advisor = getDeclareParentsAdvisor(field);

if (advisor != null) {

advisors.add(advisor);

}

}

return advisors;

}

6.处理 method,获取增强器,见代码块8。

代码块8:getAdvisor


@Override

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,

int declarationOrderInAspect, String aspectName) {

// 1.校验切面类

validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

// 2.AspectJ切点信息的获取(例如:表达式),就是指定注解的表达式信息的获取,如:@Around(“execution(* com.joonwhee.open.aop..(…))”)

AspectJExpressionPointcut expressionPointcut = getPointcut(

candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());

// 3.如果expressionPointcut为null,则直接返回null

if (expressionPointcut == null) {

return null;

}

// 4.根据切点信息生成增强器

return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,

this, aspectInstanceFactory, declarationOrderInAspect, aspectName);

}

2.AspectJ 切点信息的获取,见代码块9。

4.根据切点信息生成增强器,见代码块11。

代码块9:getPointcut


private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {

// 1.查找并返回给定方法的第一个AspectJ注解(@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut)

// 因为我们之前把@Pointcut注解的方法跳过了,所以这边必然不会获取到@Pointcut注解

AspectJAnnotation<?> aspectJAnnotation =

AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);

// 2.如果方法没有使用AspectJ的注解,则返回null

if (aspectJAnnotation == null) {

return null;

}

// 3.使用AspectJExpressionPointcut实例封装获取的信息

AspectJExpressionPointcut ajexp =

new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);

// 提取得到的注解中的表达式,

// 例如:@Around(“execution(* com.joonwhee.open.aop..(…))”),得到:execution(* com.joonwhee.open.aop..(…))

ajexp.setExpression(aspectJAnnotation.getPointcutExpression());

ajexp.setBeanFactory(this.beanFactory);

return ajexp;

}

1.获取方法上的AspectJ注解,见代码块10。

代码块10:findAspectJAnnotationOnMethod


protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {

// 设置要查找的注解类

Class<?>[] classesToLookFor = new Class<?>[]{

Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};

for (Class<?> c : classesToLookFor) {

// 查找方法上是否存在当前遍历的注解,如果有则返回

AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class) c);

if (foundAnnotation != null) {

return foundAnnotation;

}

}

return null;

}

代码块11:new InstantiationModelAwarePointcutAdvisorImpl


public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,

Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,

MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

// 1.简单的将信息封装在类的实例中

this.declaredPointcut = declaredPointcut;

this.declaringClass = aspectJAdviceMethod.getDeclaringClass();

this.methodName = aspectJAdviceMethod.getName();

this.parameterTypes = aspectJAdviceMethod.getParameterTypes();

// aspectJAdviceMethod保存的是我们用来进行逻辑增强的方法(@Around、@After等修饰的方法)

this.aspectJAdviceMethod = aspectJAdviceMethod;

this.aspectJAdvisorFactory = aspectJAdvisorFactory;

this.aspectInstanceFactory = aspectInstanceFactory;

this.declarationOrder = declarationOrder;

this.aspectName = aspectName;

// 2.是否需要延迟实例化

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;

// 3.实例化增强器:根据注解中的信息初始化对应的增强器

this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);

}

}

3.实例化增强器:根据注解中的信息初始化对应的增强器,见代码块12。

代码块12:instantiateAdvice


private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {

return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,

this.aspectInstanceFactory, this.declarationOrder, this.aspectName);

}

// ReflectiveAspectJAdvisorFactory.java

@Override

public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,

MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

// 1.获取切面类

Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();

// 2.校验切面类(重复校验第3次…)

validate(candidateAspectClass);

// 3.查找并返回方法的第一个AspectJ注解

AspectJAnnotation<?> aspectJAnnotation =

AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);

if (aspectJAnnotation == null) {

return null;

}

// If we get here, we know we have an AspectJ method.

// Check that it’s an AspectJ-annotated class

// 4.如果我们到这里,我们知道我们有一个AspectJ方法。检查切面类是否使用了AspectJ注解

if (!isAspect(candidateAspectClass)) {

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;

// 5.根据方法使用的aspectJ注解创建对应的增强器,例如最常见的@Around注解会创建AspectJAroundAdvice

switch (aspectJAnnotation.getAnnotationType()) {

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;

case AtAround:

springAdvice = new AspectJAroundAdvice(

candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);

break;

case AtPointcut:

if (logger.isDebugEnabled()) {

logger.debug(“Processing pointcut '” + candidateAdviceMethod.getName() + “'”);

}

return null;

default:

throw new UnsupportedOperationException(

"Unsupported advice type on method: " + candidateAdviceMethod);

}

// Now to configure the advice…

// 6.配置增强器

// 切面类的name,其实就是beanName

springAdvice.setAspectName(aspectName);

springAdvice.setDeclarationOrder(declarationOrder);

// 获取增强方法的参数

String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);

if (argNames != null) {

// 如果参数不为空,则赋值给springAdvice

springAdvice.setArgumentNamesFromStringArray(argNames);

}

springAdvice.calculateArgumentBindings();

// 最后,返回增强器

return springAdvice;

}

代码块13:findAdvisorsThatCanApply


public static List findAdvisorsThatCanApply(List candidateAdvisors, Class<?> clazz) {

if (candidateAdvisors.isEmpty()) {

return candidateAdvisors;

}

List eligibleAdvisors = new LinkedList();

// 1.首先处理引介增强(@DeclareParents)用的比较少可以忽略,有兴趣的参考:https://www.cnblogs.com/HigginCui/p/6322283.html

for (Advisor candidate : candidateAdvisors) {

if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {

eligibleAdvisors.add(candidate);

}

}

boolean hasIntroductions = !eligibleAdvisors.isEmpty();

// 2.遍历所有的candidateAdvisors

for (Advisor candidate : candidateAdvisors) {

// 2.1 引介增强已经处理,直接跳过

if (candidate instanceof IntroductionAdvisor) {

// already processed

continue;

}

// 2.2 正常增强处理,判断当前bean是否可以应用于当前遍历的增强器(bean是否包含在增强器的execution指定的表达式中)

if (canApply(candidate, clazz, hasIntroductions)) {

eligibleAdvisors.add(candidate);

}

}

return eligibleAdvisors;

}

2.2 正常增强处理,判断当前 bean 是否可以应用于当前遍历的增强器,这边表达式判断的逻辑比较复杂,可以简单的理解为:判断 bean 是否包含在增强器的 execution 指定的表达式中。

代码块14:createProxy


protected Object createProxy(

Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

if (this.beanFactory instanceof ConfigurableListableBeanFactory) {

AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);

}

// 1.初始化ProxyFactory

ProxyFactory proxyFactory = new ProxyFactory();

// 从当前对象复制属性值

proxyFactory.copyFrom(this);

// 检查proxyTargetClass属性,判断对于给定的bean使用类代理还是接口代理,

// proxyTargetClass值默认为false,可以通过proxy-target-class属性设置为true

if (!proxyFactory.isProxyTargetClass()) {

// 检查preserveTargetClass属性,判断beanClass是应该基于类代理还是基于接口代理

if (shouldProxyTargetClass(beanClass, beanName)) {

// 如果是基于类代理,则将proxyTargetClass赋值为true

proxyFactory.setProxyTargetClass(true);

} else {

// 评估bean的代理接口

evaluateProxyInterfaces(beanClass, proxyFactory);

}

}

// 将拦截器封装为Advisor(advice持有者)

Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);

// 将advisors添加到proxyFactory

proxyFactory.addAdvisors(advisors);

// 设置要代理的类,将targetSource赋值给proxyFactory的targetSource属性,之后可以通过该属性拿到被代理的bean的实例

proxyFactory.setTargetSource(targetSource);

// 自定义ProxyFactory,空方法,留给子类实现

customizeProxyFactory(proxyFactory);

// 用来控制proxyFactory被配置之后,是否还允许修改通知。默认值为false(即在代理被配置之后,不允许修改代理类的配置)

proxyFactory.setFrozen(this.freezeProxy);

if (advisorsPreFiltered()) {

proxyFactory.setPreFiltered(true);

}

// 2.使用proxyFactory获取代理

return proxyFactory.getProxy(getProxyClassLoader());

}

2.使用 proxyFactory 获取代理,见代码块15。

代码块15:getProxy


public Object getProxy(ClassLoader classLoader) {

// 1.createAopProxy:创建AopProxy

// 2.getProxy(classLoader):获取代理对象实例

return createAopProxy().getProxy(classLoader);

}

1.createAopProxy:创建AopProxy,见代码块16。

2.getProxy(classLoader):获取代理对象实例,跟我们自己写的代理类似,JDK 动态代理见代码块18,CGLIB 代理见代码块19。

代码块16:createAopProxy


protected final synchronized AopProxy createAopProxy() {

if (!this.active) {

// 1.激活此代理配置

activate();

}

// 2.创建AopProxy

return getAopProxyFactory().createAopProxy(this);

}

@Override

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {

// 1.判断使用JDK动态代理还是Cglib代理

// optimize:用于控制通过cglib创建的代理是否使用激进的优化策略。除非完全了解AOP如何处理代理优化,

// 否则不推荐使用这个配置,目前这个属性仅用于cglib代理,对jdk动态代理无效

// proxyTargetClass:默认为false,设置为true时,强制使用cglib代理,设置方式:<aop:aspectj-autoproxy proxy-target-class=“true” />

// hasNoUserSuppliedProxyInterfaces:config是否存在代理接口或者只有SpringProxy一个接口

if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {

// 拿到要被代理的对象的类型

Class<?> targetClass = config.getTargetClass();

if (targetClass == null) {

// TargetSource无法确定目标类:代理创建需要接口或目标。

throw new AopConfigException("TargetSource cannot determine target class: " +

“Either an interface or a target is required for proxy creation.”);

}

// 要被代理的对象是接口 || targetClass是Proxy class

// 当且仅当使用getProxyClass方法或newProxyInstance方法动态生成指定的类作为代理类时,才返回true。

if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {

// JDK动态代理,这边的入参config(AdvisedSupport)实际上是ProxyFactory对象

// 具体为:AbstractAutoProxyCreator中的proxyFactory.getProxy发起的调用,在ProxyCreatorSupport使用了this作为参数,

// 调用了的本方法,这边的this就是发起调用的proxyFactory对象,而proxyFactory对象中包含了要执行的的拦截器

return new JdkDynamicAopProxy(config);

}

// Cglib代理

return new ObjenesisCglibAopProxy(config);

} else {

// JDK动态代理

return new JdkDynamicAopProxy(config);

}

}

这边创建 AopProxy 的参数 config(AdvisedSupport)实际上是代码块14中的 proxyFactory 对象。

具体为:AbstractAutoProxyCreator 中的 proxyFactory.getProxy 发起的调用,在 ProxyCreatorSupport 使用了 this 作为参数调用了本方法,这边的 this 就是发起调用的 proxyFactory对象,而 proxyFactory 对象中包含了要执行的的拦截器(Advisor)。

无论是创建 JDK 动态代理还是 CGLIB 代理,都会传入 config 参数,该参数会被保存在 advised(AdvisedSupport)变量中,见代码块17。

代码块17:JDK 动态代理、CBLIB 代理构造函数


// JdkDynamicAopProxy.java

public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {

Assert.notNull(config, “AdvisedSupport must not be null”);

if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {

throw new AopConfigException(“No advisors and no TargetSource specified”);

}

// config赋值给advised

this.advised = config;

}

// ObjenesisCglibAopProxy.java

public ObjenesisCglibAopProxy(AdvisedSupport config) {

super(config);

}

// CglibAopProxy.java

public CglibAopProxy(AdvisedSupport config) throws AopConfigException {

Assert.notNull(config, “AdvisedSupport must not be null”);

if (config.getAdvisors().length == 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);

}

代码块18:JdkDynamicAopProxy#getProxy


@Override

public Object getProxy(ClassLoader classLoader) {

if (logger.isDebugEnabled()) {

logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());

}

// 1.拿到要被代理对象的所有接口

Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);

findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);

// 2.通过classLoader、接口、InvocationHandler实现类,来获取到代理对象

return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

}

最后

小编在这里分享些我自己平时的学习资料,由于篇幅限制,pdf文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!

程序员代码面试指南 IT名企算法与数据结构题目最优解

这是” 本程序员面试宝典!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现。针对当前程序员面试缺乏权威题目汇总这一-痛点, 本书选取将近200道真实出现过的经典代码面试题,帮助广“大程序员的面试准备做到万无一失。 “刷”完本书后,你就是“题王”!

image.png

《TCP-IP协议组(第4版)》

本书是介绍TCP/IP协议族的经典图书的最新版本。本书自第1版出版以来,就广受读者欢迎。

本书最新版进行」护元,以体境计算机网络技不的最新发展,全书古有七大部分共30草和7个附录:第一部分介绍一些基本概念和基础底层技术:第二部分介绍网络层协议:第三部分介绍运输层协议;第四部分介绍应用层协议:第五部分介绍下一代协议,即IPv6协议:第六部分介绍网络安全问题:第七部分给出了7个附录。

image.png

Java开发手册(嵩山版)

这个不用多说了,阿里的开发手册,每次更新我都会看,这是8月初最新更新的**(嵩山版)**

image.png

MySQL 8从入门到精通

本书主要内容包括MySQL的安装与配置、数据库的创建、数据表的创建、数据类型和运算符、MySQL 函数、查询数据、数据表的操作(插入、更新与删除数据)、索引、存储过程和函数、视图、触发器、用户管理、数据备份与还原、MySQL 日志、性能优化、MySQL Repl ication、MySQL Workbench、 MySQL Utilities、 MySQL Proxy、PHP操作MySQL数据库和PDO数据库抽象类库等。最后通过3个综合案例的数据库设计,进步讲述 MySQL在实际工作中的应用。

image.png

Spring5高级编程(第5版)

本书涵盖Spring 5的所有内容,如果想要充分利用这一领先的企业级 Java应用程序开发框架的强大功能,本书是最全面的Spring参考和实用指南。

本书第5版涵盖核心的Spring及其与其他领先的Java技术(比如Hibemate JPA 2.Tls、Thymeleaf和WebSocket)的集成。本书的重点是介绍如何使用Java配置类、lambda 表达式、Spring Boot以及反应式编程。同时,将与企业级应用程序开发人员分享一些见解和实际经验,包括远程处理、事务、Web 和表示层,等等。

image.png

JAVA核心知识点+1000道 互联网Java工程师面试题

image.png

image.png

企业IT架构转型之道 阿里巴巴中台战略思想与架构实战

本书讲述了阿里巴巴的技术发展史,同时也是-部互联网技 术架构的实践与发展史。

image.png

找小编(vip1024c)领取
自第1版出版以来,就广受读者欢迎。

本书最新版进行」护元,以体境计算机网络技不的最新发展,全书古有七大部分共30草和7个附录:第一部分介绍一些基本概念和基础底层技术:第二部分介绍网络层协议:第三部分介绍运输层协议;第四部分介绍应用层协议:第五部分介绍下一代协议,即IPv6协议:第六部分介绍网络安全问题:第七部分给出了7个附录。

[外链图片转存中…(img-b8IMvdXZ-1721720400747)]

Java开发手册(嵩山版)

这个不用多说了,阿里的开发手册,每次更新我都会看,这是8月初最新更新的**(嵩山版)**

[外链图片转存中…(img-EiGIFXnn-1721720400748)]

MySQL 8从入门到精通

本书主要内容包括MySQL的安装与配置、数据库的创建、数据表的创建、数据类型和运算符、MySQL 函数、查询数据、数据表的操作(插入、更新与删除数据)、索引、存储过程和函数、视图、触发器、用户管理、数据备份与还原、MySQL 日志、性能优化、MySQL Repl ication、MySQL Workbench、 MySQL Utilities、 MySQL Proxy、PHP操作MySQL数据库和PDO数据库抽象类库等。最后通过3个综合案例的数据库设计,进步讲述 MySQL在实际工作中的应用。

[外链图片转存中…(img-K1yC7nq1-1721720400748)]

Spring5高级编程(第5版)

本书涵盖Spring 5的所有内容,如果想要充分利用这一领先的企业级 Java应用程序开发框架的强大功能,本书是最全面的Spring参考和实用指南。

本书第5版涵盖核心的Spring及其与其他领先的Java技术(比如Hibemate JPA 2.Tls、Thymeleaf和WebSocket)的集成。本书的重点是介绍如何使用Java配置类、lambda 表达式、Spring Boot以及反应式编程。同时,将与企业级应用程序开发人员分享一些见解和实际经验,包括远程处理、事务、Web 和表示层,等等。

[外链图片转存中…(img-7BL1Z9kI-1721720400749)]

JAVA核心知识点+1000道 互联网Java工程师面试题

[外链图片转存中…(img-1fLeLooj-1721720400749)]

[外链图片转存中…(img-lPIRbrYI-1721720400749)]

企业IT架构转型之道 阿里巴巴中台战略思想与架构实战

本书讲述了阿里巴巴的技术发展史,同时也是-部互联网技 术架构的实践与发展史。

[外链图片转存中…(img-EhTpm1jY-1721720400750)]

找小编(vip1024c)领取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值