Spring源码
参考资料
https://www.bilibili.com/video/BV1Tz4y1a7FM
https://www.bilibili.com/video/BV1iz4y1b75q
bean工厂
DefaultListableBeanFactory(最原始)
bean的生命周期
创建(实例化)–>依赖注入–>-初始化–>销毁
bean–>推断构造方法(默认是无参构造,或指定的构造方法)–>实例化成普通对象(相当于new bean)
–>进行依赖注入(bean里的属性)–>执行afterPropertiesSet()(InitializingBean的一个回调方法,同@PostConstruct)
–>初始化后是否需要AOP–>AOP–>代理对象(target=普通对象)–>把对象放入Map<beanname,bean对象>单例池
//真正创建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);
- 创建的A放入 Set singletonsCurrentlyInCreation(只要创建就放入set,表示bean正在初始化)
- 首先是实例化,new 普通对象,addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));为了防止循环引用,尽早持有对象的引用,第二个参数是一个lamda表达式可用来获取普通对象
- 在A填充B时,B需要注入A,判断A正在初始化,此时出现循环依赖
- 先向二级缓存里查找,在多方循环中保证创建的是都是同一个代理对象A
- 再向三级缓存里查找,没有则执行lamda获取普通对象,并且进行AOP,生成代理对象
- 放入bean到二级缓存中
- 填充其他的属性
- 进行Aop的逻辑,若是循环依赖则会提前进行Aop(step5)而不是现在
- 在二级缓存里查找,是不是已经有已经生成好的bean
- 添加到单例池
- Set中removeA,标识初始化完成
beanFactory
四个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;
}
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;
}
}
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回调
为什么不用@Autowired
简单地说:
@Autowired 的解析需要用到 bean后处理器,属于扩展功能,而Aware接口属于内置功能,不加任何扩展,Spring就能识别某些情况下,扩展功能会失效,而内置功能不会失效
例2: Java配置类在添加了 bean 工厂后处理器后,你会发现用传统接口方式的注入和初始化仍然成功,而@Autowired 和@PostConstruct的注入和初始化失败
三种初始化方法
@PostConstruct
实现InitializingBean接口的afterPropertiesset()方法
@Bean(initMethod=“”)
执行顺序优先级从高到低
三种销毁方法
@PreDestroy
实现DisposableBean的destroy()
@Bean(destroyMethod=“”)
执行顺序优先级从高到低
五种Scope
在Java中,常见的五种Scope(作用域)是:
- Singleton(单例):在整个应用程序中只创建一个实例,所有对该类的引用都指向同一个对象实例。
- Prototype(原型):每次请求时都会创建一个新的实例,每个实例都是独立的。
- Request(请求):每个HTTP请求都会创建一个新的实例,在同一个请求中共享同一个实例,但不同请求之间的实例是独立的。
- Session(会话):每个用户会话(Session)期间只创建一个实例,在同一个用户会话中共享同一个实例,不同用户之间的实例是独立的。
- Application(应用):在整个Web应用程序的生命周期中只创建一个实例,所有用户共享同一个实例。
这些Scope主要用于Spring框架中的依赖注入管理,通过在Bean的定义中指定不同的Scope,控制对象的创建和共享方式。每种Scope都有其特定的使用场景和适用范围,可以根据需求选择合适的Scope来管理对象的生命周期和共享方式。
使用场景
- Singleton(单例):适用于需要在整个应用程序中共享和复用同一个实例的情况。比如,全局的配置对象、线程池、日志管理器等只需要一个实例来处理整个应用程序的请求。
- Prototype(原型):适用于每次请求都需要获得一个新的、独立的实例的情况。比如,每次请求都需要创建一个新的订单对象或邮件发送对象等,保证对象之间的隔离性。
- Request(请求):适用于每个HTTP请求需要获得一个新的实例,并且同一个请求中多个组件需要共享同一个实例的情况。比如,在Web应用程序中,不同组件需要访问同一个请求相关的数据或状态的场景。
- Session(会话):适用于需要在特定用户会话期间共享和保持同一个实例的情况。比如,保存用户登录状态、用户购物车等与特定用户相关联的数据的组件,确保同一个用户在同一个会话期间使用的是同一个实例。
- Application(应用):适用于需要在整个Web应用程序的生命周期中共享和保持同一个实例的情况。比如,全局的缓存对象、全局的应用程序状态等,确保整个应用程序共享的是同一个实例。
解决单例注入其他作用域
AOP
概念
AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,它通过将横切关注点(Cross-cutting Concerns)从主体逻辑中分离出来,以模块化地实现跨多个部分的功能复用。
在传统的面向对象编程中,我们将程序的主要逻辑抽象为类和方法,但横切关注点(例如日志记录、事务管理、权限控制等)常常散布在整个应用程序中。这种散布导致了代码的重复性和难以维护性。而AOP的目标就是解决这个问题,通过将横切关注点与主体逻辑分离,使得关注点的修改和维护更加集中和方便。
AOP的核心概念包括:
- 切面(Aspect):切面是横切关注点的模块化,它定义了横切关注点的行为和逻辑。一个切面可以横跨多个类或模块,并在特定的连接点(Join Point)上执行自己的逻辑。
- 连接点(Join Point):连接点表示在程序执行过程中可以插入切面的位置,比如方法调用、方法执行前后、字段访问等。
- 通知(Advice):通知是切面在连接点上执行的动作,可以是在方法调用前后执行、方法抛出异常时执行等。
- 切点(Pointcut):切点是一组连接点的集合,它定义了那些连接点将被切面处理。
- 引入(Introduction):引入允许在不修改原有类的情况下,向现有类添加新的方法和属性。
- 织入(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。
在切面类中定义了两个通知方法beforeMethodExecution
和afterMethodExecution
,分别在目标方法执行前和执行后执行。这里通过@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);
}
}
现在,当调用UserService
的addUser()
和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编译器就可以直接实现方法增强
agent增强
通过jvm设置参数,在类加载阶段通过修改类的字节码做到增强
ps:可以通过阿里的arthas工具来反编译类加载阶段的class
JDK代理
只针对接口代理,代理平级,实现共同接口
JDK代理(JDK Proxy)是Java中的一种动态代理机制,它基于接口实现。Java提供了一个java.lang.reflect.Proxy
类和java.lang.reflect.InvocationHandler
接口,用于创建动态代理对象并处理方法调用。
使用JDK代理,需要满足以下条件:
- 目标类必须实现一个或多个接口。
- 创建一个实现
InvocationHandler
接口的代理处理器类,该处理器类负责真正的代理逻辑。 - 使用
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接口,可以在运行时创建代理对象,并在方法调用前后添加额外逻辑。
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 动态代理。文章来源:https://www.toymoban.com/news/detail-657782.html
文章来源地址https://www.toymoban.com/news/detail-657782.html
到了这里,关于【Spring源码】小白速通解析Spring源码,从0到1,持续更新!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!