【Spring源码】小白速通解析Spring源码,从0到1,持续更新!

Spring源码

参考资料

https://www.bilibili.com/video/BV1Tz4y1a7FM

https://www.bilibili.com/video/BV1iz4y1b75q

image-20230727230632443

bean工厂

DefaultListableBeanFactory(最原始)

bean的生命周期

创建(实例化)–>依赖注入–>-初始化–>销毁

bean–>推断构造方法(默认是无参构造,或指定的构造方法)–>实例化成普通对象(相当于new bean)

–>进行依赖注入(bean里的属性)–>执行afterPropertiesSet()(InitializingBean的一个回调方法,同@PostConstruct)

–>初始化后是否需要AOP–>AOP–>代理对象(target=普通对象)–>把对象放入Map<beanname,bean对象>单例池

image-20230817225424846

//真正创建Bean的方法
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		//封装被创建的Bean对象
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		//获取实例化对象的类型
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		//调用PostProcessor后置处理器
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		//向容器中缓存单例模式的Bean对象,以防循环引用
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			//这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		//Bean对象的初始化,依赖注入在此触发
		//这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean
		Object exposedObject = bean;
		try {
			//将Bean实例对象封装,并且Bean定义中配置的属性值赋值给实例对象
			populateBean(beanName, mbd, instanceWrapper);
			//初始化Bean对象
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		if (earlySingletonExposure) {
			//获取指定名称的已注册的单例模式Bean对象
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				//根据名称获取的已注册的Bean和正在实例化的Bean是同一个
				if (exposedObject == bean) {
					//当前实例化的Bean初始化完成
					exposedObject = earlySingletonReference;
				}
				//当前Bean依赖其他Bean,并且当发生循环引用时不允许新创建实例对象
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					//获取当前Bean所依赖的其他Bean
					for (String dependentBean : dependentBeans) {
						//对依赖Bean进行类型检查
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		//注册完成依赖注入的Bean
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}
//初始容器创建的Bean实例对象,为其添加BeanPostProcessor后置处理器
	protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		//JDK的安全机制验证权限
		if (System.getSecurityManager() != null) {
			//实现PrivilegedAction接口的匿名内部类
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			//为Bean实例对象包装相关属性,如名称,类加载器,所属容器等信息
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		//对BeanPostProcessor后置处理器的postProcessBeforeInitialization
		//回调方法的调用,为Bean实例初始化前做一些处理
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		//调用Bean实例对象初始化的方法,这个初始化方法是在Spring Bean定义配置
		//文件中通过init-method属性指定的
		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		//对BeanPostProcessor后置处理器的postProcessAfterInitialization
		//回调方法的调用,为Bean实例初始化之后做一些处理
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

三级缓存解决循环依赖

循环依赖

在A创建的过程中,A的属性B需要注入属性A

  • singletonObjects(一级缓存)
  • earlysingletonObjects(二级缓存)
  • singletonFactories(三级缓存)
  • private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
    private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16);
  1. 创建的A放入 Set singletonsCurrentlyInCreation(只要创建就放入set,表示bean正在初始化)
  2. 首先是实例化,new 普通对象,addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));为了防止循环引用,尽早持有对象的引用,第二个参数是一个lamda表达式可用来获取普通对象
  3. 在A填充B时,B需要注入A,判断A正在初始化,此时出现循环依赖
  4. 先向二级缓存里查找,在多方循环中保证创建的是都是同一个代理对象A
  5. 再向三级缓存里查找,没有则执行lamda获取普通对象,并且进行AOP,生成代理对象
  6. 放入bean到二级缓存中
  7. 填充其他的属性
  8. 进行Aop的逻辑,若是循环依赖则会提前进行Aop(step5)而不是现在
  9. 在二级缓存里查找,是不是已经有已经生成好的bean
  10. 添加到单例池
  11. Set中removeA,标识初始化完成

beanFactory

image-20230816230618815

四个Applicationcontext

FileSystemXmlApplicationContext

ClassPathXmlApplicationContext

AnnotationConfigApplicationContext

AnnotationConfigWebApplicationContext

GenericApplicationContext(是一个干净的容器)

后置处理器(PostProcessor)

CommonAnnotationBeanPostProcessor

Ordered.LOWEST_PRECEDENCE - 3

@Resource @PostConstruct @PreDestroy

解析WebService关于JAX-WS的相关注解,EJB相关的注解

AutowiredAnnotationBeanPostProcessor

Ordered.LOWEST_PRECEDENCE - 2

处理@Autowire注解,@Value注解,处理javax.inject.Inject JSR-330注解

	//处理类中的属性
	@Override
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

		//获取指定类中autowire相关注解的元信息
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
			//对Bean的属性进行自动注入
			metadata.inject(bean, beanName, pvs);
		}
		catch (BeanCreationException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		}
		return pvs;
	}

image-20230818000115153

BeanPostProcessor

处理器定义了Bean 初始化 前后执行的方法。

public interface BeanPostProcessor {

    //自定义初始化方法之前执行
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    //自定义初始化方法之后执行
    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

}

InstantiationAwareBeanPostProcessor

该处理器定义了Bean 实例化 前后执行的方法。

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
    //实例化之前
    @Nullable
    default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { 
        //这里可以自定义代理类
        return null;
    }

    //实例化后-但是执行在初始化之前
    default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }

    //处理bean的Properties值
    @Nullable
    default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
            throws BeansException {

        return null;
    }

}

image-20230817234200283

DestructionAwareBeanPostProcessor

该处理器了销毁Bean之前的操作。

public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {

    //bean销毁之前
    void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;

    //bean是否需要销毁
    default boolean requiresDestruction(Object bean) {
        return true;
    }

}

工厂后置处理器-扫描

AnnotationBeanNameGenerator(bean名构造器)

MetadataReader(类信息)

AnnotationMetadata(注解信息)

ClassPathBeanDefinitionScanner(mapperscaner)

一、自定义Bean 后处理器 Processor

package com.mangoubiubiu.show.a05.component;

import com.mangoubiubiu.show.a05.Config;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

import java.io.IOException;

public class ComponentScanPostProcessor implements BeanFactoryPostProcessor {

    /**
     * context.refresh   初始化ApplicationContext的时候会回调这个方法
     * @param configurableListableBeanFactory
     * @throws BeansException
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

        try {

            //Spring工具类 读取类的源信息
            CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
            //查找某个类上有没有加注解 第一个参数 某个类的类型  第二个参数 要找的注解
            ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
            if(componentScan!=null){
                for (String p:componentScan.basePackages()) {
                    System.out.println("包名:"+p);


                    AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();

                    //com.mangoubiubiu.show.a05.component
                    StringBuilder path = new StringBuilder();
                    path.append("classpath*:").append(p.replace(".","/")).append("/**/*.class");
                    System.out.println("拼接后的包名:"+path.toString());
                    //读取路径下的文件
        Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path.toString());
                    for (Resource res:resources) {
                        System.out.println("读取到的文件信息为:"+res);
                        MetadataReader reader = factory.getMetadataReader(res);
                        System.out.println("得到类信息:"+ reader.getClassMetadata().getClassName());
                        AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
	System.out.println("是否加了Component注解"+ annotationMetadata.hasAnnotation(Component.class.getName()));
    System.out.println("是否加了Component注解 派生"+ annotationMetadata.hasMetaAnnotation(Component.class.getName()));

                        if(annotationMetadata.hasAnnotation(Component.class.getName()) || annotationMetadata.hasMetaAnnotation(Component.class.getName())){
                            AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(reader.getClassMetadata().getClassName()).getBeanDefinition();

                            if (configurableListableBeanFactory instanceof DefaultListableBeanFactory  ) {
                                DefaultListableBeanFactory beanFactory = ((DefaultListableBeanFactory) configurableListableBeanFactory);
                                String beanName = generator.generateBeanName(beanDefinition, beanFactory);
                                beanFactory.registerBeanDefinition(beanName,beanDefinition);
                            }
                        }


                    }


                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

二、将ComponentScanPostProcessor 注入到容器里面

package com.mangoubiubiu.show.a05;

import com.mangoubiubiu.show.a05.component.ComponentScanPostProcessor;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

import java.awt.*;
import java.io.IOException;

@Slf4j
public class A05Application {

    private MetadataReader reader;

    public static void main(String[] args) throws IOException {
        GenericApplicationContext context = new GenericApplicationContext();
        //将config注册到容器里面
        context.registerBean("config",Config.class);
        context.registerBean(ComponentScanPostProcessor.class);
//        context.registerBean(MapperScannerConfigurer.class,beanDefinition -> {
//            beanDefinition.getPropertyValues().add("basePackage","com.mangoubiubiu.show.a05.mapper");
//        });



        //初始化容器

        context.refresh();

        for (String name: context.getBeanDefinitionNames()) {
            System.out.println(name);
        }

        context.close();
    }



}

同理@Bean和@Mapper

Aware回调

image-20230820233150252

为什么不用@Autowired

简单地说:
@Autowired 的解析需要用到 bean后处理器,属于扩展功能,而Aware接口属于内置功能,不加任何扩展,Spring就能识别某些情况下,扩展功能会失效,而内置功能不会失效

例2: Java配置类在添加了 bean 工厂后处理器后,你会发现用传统接口方式的注入和初始化仍然成功,而@Autowired 和@PostConstruct的注入和初始化失败

image-20230820234334671

image-20230820234626708

三种初始化方法

@PostConstruct

实现InitializingBean接口的afterPropertiesset()方法

@Bean(initMethod=“”)

执行顺序优先级从高到低

三种销毁方法

@PreDestroy

实现DisposableBean的destroy()

@Bean(destroyMethod=“”)

执行顺序优先级从高到低

五种Scope

在Java中,常见的五种Scope(作用域)是:

  1. Singleton(单例):在整个应用程序中只创建一个实例,所有对该类的引用都指向同一个对象实例。
  2. Prototype(原型):每次请求时都会创建一个新的实例,每个实例都是独立的。
  3. Request(请求):每个HTTP请求都会创建一个新的实例,在同一个请求中共享同一个实例,但不同请求之间的实例是独立的。
  4. Session(会话):每个用户会话(Session)期间只创建一个实例,在同一个用户会话中共享同一个实例,不同用户之间的实例是独立的。
  5. Application(应用):在整个Web应用程序的生命周期中只创建一个实例,所有用户共享同一个实例。

这些Scope主要用于Spring框架中的依赖注入管理,通过在Bean的定义中指定不同的Scope,控制对象的创建和共享方式。每种Scope都有其特定的使用场景和适用范围,可以根据需求选择合适的Scope来管理对象的生命周期和共享方式。

使用场景

  1. Singleton(单例):适用于需要在整个应用程序中共享和复用同一个实例的情况。比如,全局的配置对象、线程池、日志管理器等只需要一个实例来处理整个应用程序的请求。
  2. Prototype(原型):适用于每次请求都需要获得一个新的、独立的实例的情况。比如,每次请求都需要创建一个新的订单对象或邮件发送对象等,保证对象之间的隔离性。
  3. Request(请求):适用于每个HTTP请求需要获得一个新的实例,并且同一个请求中多个组件需要共享同一个实例的情况。比如,在Web应用程序中,不同组件需要访问同一个请求相关的数据或状态的场景。
  4. Session(会话):适用于需要在特定用户会话期间共享和保持同一个实例的情况。比如,保存用户登录状态、用户购物车等与特定用户相关联的数据的组件,确保同一个用户在同一个会话期间使用的是同一个实例。
  5. Application(应用):适用于需要在整个Web应用程序的生命周期中共享和保持同一个实例的情况。比如,全局的缓存对象、全局的应用程序状态等,确保整个应用程序共享的是同一个实例。

解决单例注入其他作用域

image-20230822001543542

AOP

概念

AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,它通过将横切关注点(Cross-cutting Concerns)从主体逻辑中分离出来,以模块化地实现跨多个部分的功能复用。

在传统的面向对象编程中,我们将程序的主要逻辑抽象为类和方法,但横切关注点(例如日志记录、事务管理、权限控制等)常常散布在整个应用程序中。这种散布导致了代码的重复性和难以维护性。而AOP的目标就是解决这个问题,通过将横切关注点与主体逻辑分离,使得关注点的修改和维护更加集中和方便。

AOP的核心概念包括:

  1. 切面(Aspect):切面是横切关注点的模块化,它定义了横切关注点的行为和逻辑。一个切面可以横跨多个类或模块,并在特定的连接点(Join Point)上执行自己的逻辑。
  2. 连接点(Join Point):连接点表示在程序执行过程中可以插入切面的位置,比如方法调用、方法执行前后、字段访问等。
  3. 通知(Advice):通知是切面在连接点上执行的动作,可以是在方法调用前后执行、方法抛出异常时执行等。
  4. 切点(Pointcut):切点是一组连接点的集合,它定义了那些连接点将被切面处理。
  5. 引入(Introduction):引入允许在不修改原有类的情况下,向现有类添加新的方法和属性。
  6. 织入(Weaving):织入是将切面应用到目标对象来创建新的代理对象的过程。织入可以在编译时、类加载时或运行时进行。

通过使用AOP,我们可以将关注点的代码从主体业务逻辑中分离出来,提高了代码的可重用性、可维护性和可理解性。常见的AOP框架有Spring AOP和AspectJ等。这些框架提供了强大的AOP功能和灵活的配置方式,使得我们能够更加方便地实现面向切面编程。

AOP示例和场景应用

以下是一个简单的AOP示例,使用Spring AOP框架进行切面编程:

假设我们有一个业务类UserService,其中有两个方法addUser()deleteUser()。我们希望在这两个方法执行前后记录日志。

首先,定义一个切面类LoggingAspect,用于实现日志记录逻辑:

javaCopy Codeimport org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    @Before("execution(* com.example.UserService.addUser(..)) || execution(* com.example.UserService.deleteUser(..))")
    public void beforeMethodExecution(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Before executing method: " + methodName);
    }

    @After("execution(* com.example.UserService.addUser(..)) || execution(* com.example.UserService.deleteUser(..))")
    public void afterMethodExecution(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("After executing method: " + methodName);
    }
}

切面类LoggingAspect使用了@Aspect@Component注解,表示它是一个切面,并且可以被Spring自动扫描和注册为Bean。

在切面类中定义了两个通知方法beforeMethodExecutionafterMethodExecution,分别在目标方法执行前和执行后执行。这里通过@Before@After注解来指定切入点表达式,对UserService类的addUser()deleteUser()方法进行拦截。

接下来,在Spring配置文件中进行相关的配置:

xmlCopy Code<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 扫描切面类 -->
    <bean class="com.example.LoggingAspect" />

    <!-- 启用AOP支持 -->
    <aop:aspectj-autoproxy />
    
    <!-- 其他配置 -->

</beans>

在配置文件中,我们使用<bean>标签来注册切面类LoggingAspect,并使用<aop:aspectj-autoproxy>标签启用AOP支持。

最后,在UserService类中调用目标方法:

javaCopy Codepackage com.example;

import org.springframework.stereotype.Service;

@Service
public class UserService {

    public void addUser(String username) {
        System.out.println("Adding user: " + username);
    }

    public void deleteUser(String username) {
        System.out.println("Deleting user: " + username);
    }
}

现在,当调用UserServiceaddUser()deleteUser()方法时,切面类LoggingAspect的通知方法会在方法执行前后被触发,实现了日志记录的功能。

注意:上述示例中使用了Spring框架的AOP支持,因此需要依赖相关的Spring库,并将配置文件与项目正确关联。如果想使用纯AspectJ框架,可以参考AspectJ的官方文档进行配置和使用。

切入点表达式

execution(* com.example.UserService.addUser(..))是一个切入点表达式,用于匹配目标方法的执行。下面是该表达式的详细解释:

  • execution: 表达式的起始关键字,表示匹配方法的执行。
  • *: 通配符,表示匹配任意返回类型的方法。
  • com.example.UserService: 表示包名为com.example,类名为UserService的类。
  • addUser: 表示要匹配的方法名为addUser
  • (..): 表示方法参数的匹配规则。这里的(..)表示匹配任意个数、任意类型的参数。

因此,execution(* com.example.UserService.addUser(..))的含义是:匹配任意返回类型、在com.example.UserService类中名为addUser的方法,并且方法参数可以是任意个数、任意类型。

这个切入点表达式可以用于AOP中的注解、XML配置或者编程方式进行切入点的定义。它告诉AOP框架,在目标方法执行前后触发切面逻辑。如果需要匹配其他方法或修改匹配规则,可以根据实际情况进行相应的修改。

ajc编译器

@Aspect

在使用@Aspec注解时,并不会被spring动态代理,而是直接修改class文件,通过ajc编译器就可以直接实现方法增强

image-20230823003313850

agent增强

通过jvm设置参数,在类加载阶段通过修改类的字节码做到增强

ps:可以通过阿里的arthas工具来反编译类加载阶段的class

image-20230823004345096JDK代理

只针对接口代理,代理平级,实现共同接口

JDK代理(JDK Proxy)是Java中的一种动态代理机制,它基于接口实现。Java提供了一个java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口,用于创建动态代理对象并处理方法调用。

使用JDK代理,需要满足以下条件:

  1. 目标类必须实现一个或多个接口。
  2. 创建一个实现InvocationHandler接口的代理处理器类,该处理器类负责真正的代理逻辑。
  3. 使用Proxy.newProxyInstance()方法创建代理对象,该方法接受目标类的ClassLoader、接口数组和代理处理器作为参数。

下面是一个简单的示例:

javaCopy Codeimport java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

interface MyInterface {
    void doSomething();
}

class MyTargetClass implements MyInterface {
    public void doSomething() {
        System.out.println("Doing something...");
    }
}

class MyInvocationHandler implements InvocationHandler {
    private Object target;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method invocation");
        Object result = method.invoke(target, args);
        System.out.println("After method invocation");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        MyInterface targetObject = new MyTargetClass();
        InvocationHandler invocationHandler = new MyInvocationHandler(targetObject);
        MyInterface proxyObject = (MyInterface) Proxy.newProxyInstance(
                targetObject.getClass().getClassLoader(),
                targetObject.getClass().getInterfaces(),
                invocationHandler);

        proxyObject.doSomething();
    }
}

在上面的示例中,MyInterface 是一个接口,MyTargetClass 是实现了该接口的目标类。MyInvocationHandler 是代理处理器类,它实现了InvocationHandler接口,负责在方法调用前后添加额外逻辑。在Main类的main方法中,通过Proxy.newProxyInstance()方法创建了一个代理对象proxyObject,并对MyInterface接口的方法调用进行了拦截和处理。

总之,JDK代理是一种基于接口的动态代理机制,使用JDK提供的Proxy类和InvocationHandler接口,可以在运行时创建代理对象,并在方法调用前后添加额外逻辑。

image-20230823010057018

CGLIB代理

代理子,目标父,目标类不能finnal修饰报错,finnal修饰的方法也不能增强

默认情况下,Spring AOP 使用 CGLIB(Code Generation Library)作为代理机制。CGLIB是一个强大的基于字节码生成的开源库,它能够在运行时动态地创建目标对象的子类,并覆盖其中的方法以实现切面逻辑。

当目标对象没有实现任何接口时,Spring AOP 将使用 CGLIB 代理。这样可以在运行时生成一个继承自目标对象的子类,并将切面逻辑织入到子类中。在运行时,通过代理对象调用方法时,会先执行切面逻辑,然后再调用目标方法。

但是如果目标对象实现了接口,Spring AOP 也可以选择使用 JDK 动态代理(Java Dynamic Proxy)作为代理机制。JDK 动态代理是 Java 标准库中提供的一种代理方式,通过实现目标对象实现的接口,在运行时生成代理对象,并将切面逻辑织入到代理对象的方法中。

可以通过配置来强制使用CGLIB代理或者JDK动态代理。例如,可以使用<aop:config>配置元素的 proxy-target-class 属性来指定是否使用CGLIB代理。

xmlCopy Code<aop:config proxy-target-class="true">
    <!-- 配置切面和通知 -->
</aop:config>

总之,Spring AOP 默认使用 CGLIB 作为代理机制,但也可以根据情况自动选择使用 JDK 动态代理。

image-20230823011650599

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个非常广泛和深入的话题,需要对Spring框架有深入的理解和对Java编程语言的熟悉程度。以下是一些可能涉及到的方面: 1. Spring框架的基本架构和设计模式:Spring采用了依赖注入和面向切面编程等设计模式,这些模式都是为了提高代码的可读性、可维护性和可扩展性。 2. Spring的IoC容器:Spring的IoC容器是整个框架的核心,它负责管理Bean的生命周期、依赖关系和作用域等。对于Spring码的深入解析,需要对IoC容器的实现原理和核心类进行研究。 3. Spring的AOP框架:Spring的AOP框架是基于动态代理实现的,它可以帮助我们在不修改原有代码的情况下,实现横切关注点的功能,比如日志记录、事务管理等。对于Spring码的深入解析,需要对AOP框架的实现原理和核心类进行研究。 4. Spring MVC框架:Spring MVC框架是基于前端控制器模式实现的,它可以帮助我们实现Web应用的分层架构和业务逻辑的解耦。对于Spring码的深入解析,需要对MVC框架的实现原理和核心类进行研究。 5. 其他功能模块:Spring还提供了很多其他的功能模块,比如Spring Data、Spring Security、Spring Integration等。对于这些功能模块的深入解析,需要对相应的实现原理和核心类进行研究。 总之,深入理解Spring码需要不断学习和思考,需要从多个角度去分析和探究,同时也需要结合实际项目开发经验去理解和应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值