文章目录
AOP
Spring的另一个核心是AOP,AOP全称Aspect-Oriented Programming
译为面向切面编程。AOP可以说是对OOP(面向对象编程)的补充和完善,在程序原有的纵向执行流程中,针对某一个或某些方法添加通知,形成横切面的过程就叫做面向切面编程。简单来说,用于通过在方法执行前、执行后或抛出异常时动态地添加额外的功能就是面向切面编程。AOP 可以帮助解耦应用程序的横切关注点,如日志记录、事务管理、性能监控等,从而提高代码的模块性和复用性。
实现AOP的技术,主要分为两类,一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“切面”,从而使得编译器可以在编译期间织入有关“切面”的代码,属于静态代理。AOP的工作原理主要基于对程序执行过程中特定点的拦截和增强。动态代理刚好就可以实现这个功能,AOP用的就是动态代理。
使用AOP
使用AOP大致可以分为三步:
- 将业务逻辑组件和切面类都加入到容器中,并用
Component
、@Aspect
注解标注切面类。@Aspect @Component public class LoggingAspect {}
- 在切面类的通知方法上,要注意切面表达式的写法,标注通知注解,告诉
Spring
何时何地的运行:@Before
:前置通知,在目标方法运行之前执行;@After
:后置通知,在目标方法运行之后执行,无论方法是否出现异常都会执行;@Around
:环绕通知,通过joinPoint.proceed()
方法手动控制目标方法的执行;@AfterThrowing
:异常通知,在目标方法出现异常之后执行;@AfterReturning
:返回通知,在目标方法返回之后执行;
@Aspect @Component public class LoggingAspect { @Before("execution(* com.example.service.*.*(..))") public void logBefore() { System.out.println("Executing method in service layer..."); } @After("execution(* com.example.service.*.*(..))") public void logAfter() { System.out.println("Method execution completed."); } @Around("execution(* com.example.service.*.*(..))") public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("Before method execution."); Object result = joinPoint.proceed(); System.out.println("After method execution."); return result; } @AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "error") public void logAfterThrowing(Throwable error) { System.out.println("Exception occurred: " + error); } @AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result") public void logAfterReturning(Object result) { System.out.println("Method returned value: " + result); } }
- 使用
@EnableAspectJAutoProxy
开启基于注解的AOP模式。@SpringBootApplication @EnableAspectJAutoProxy public class SpringAopApplication { public static void main(String[] args) { SpringApplication.run(SpringAopApplication.class, args); } }
execution表达式
execution
表达式用于定义切入点,作用是什么时候触发切面。execution
表达式语法:
execution(modifiers-pattern ret-type-pattern declaring-type-pattern name-pattern(param-pattern) throws-pattern)
modifiers-pattern
(可选):方法修饰符模式,如public
、protected
。ret-type-pattern
:返回类型模式,可以是具体类型,如String
,也可以是通配符(*
表示任意返回类型)。declaring-type-pattern
(可选):声明类型模式,即方法所属的类或接口,可以是具体类名,如com.example.MyClass
或通配符,如com.example.*
。name-pattern
:方法名模式,可以是具体方法名(如myMethod
),也可以是通配符(如*
表示任意方法名)。param-pattern
:参数模式,可以是具体参数类型,如(String, int)
,也可以是通配符,如(..)
表示任意参数类型和数量。throws-pattern
(可选):异常模式,可以是具体异常类型,如throws IOException
。
execution
表达式举例:
- 匹配任意方法。
@Before("execution(* *(..))") public void logBeforeAllMethods() { System.out.println("Executing any method..."); }
- 匹配特定类的所有方法。
@Before("execution(* com.example.MyClass.*(..))") public void logBeforeMyClassMethods() { System.out.println("Executing method in MyClass..."); }
- 匹配特定包中的所有方法。
@Before("execution(* com.example..*.*(..))") public void logBeforePackageMethods() { System.out.println("Executing method in com.example package..."); }
- 匹配特定返回类型的方法。
@Before("execution(String *(..))") public void logBeforeStringMethods() { System.out.println("Executing method with String return type..."); }
- 匹配特定方法名。
@Before("execution(* myMethod(..))") public void logBeforeMyMethod() { System.out.println("Executing myMethod..."); }
- 匹配特定参数类型的方法。
@Before("execution(* *(String, int))") public void logBeforeStringIntMethods() { System.out.println("Executing method with String and int parameters..."); }
- 匹配没有参数的方法。
@Before("execution(* *())") public void logBeforeNoArgMethods() { System.out.println("Executing no-arg method..."); }
- 匹配带有特定修饰符的方法。
@Before("execution(public * *(..))") public void logBeforePublicMethods() { System.out.println("Executing public method..."); }
切面执行顺序
在Spring AOP中,注意切面执行顺序非常重要,因为不同切面可能会对同一个方法执行不同的逻辑,这些逻辑的执行顺序可能会影响应用程序的行为和结果。
举一个例子,一个简单的银行转账操作,其中涉及日志记录、事务管理和安全检查三个切面。如果不考虑AOP的顺序,就是按照Spring加载顺序来,可能会导致事务管理在安全检查、日志记录的前面,这样可能会造成一些不安全的操作会被执行。但是我们期望的是先执行安全检查,再执行事务管理,最后再执行日志记录。
@Order(1) // 优先级最高
public class SecurityAspect {
@Before("execution(* com.example.service.BankService.transfer(..))")
public void checkSecurity() {
System.out.println("Security: Performing security check...");
}
}
@Order(2) // 优先级中等
public class TransactionAspect {
@Before("execution(* com.example.service.BankService.transfer(..))")
public void startTransaction() {
System.out.println("Transaction: Starting transaction...");
}
}
@Order(3) // 优先级最低
public class LoggingAspect {
@Before("execution(* com.example.service.BankService.transfer(..))")
public void logBefore() {
System.out.println("Logging: Starting method execution...");
}
}
AOP工作原理
要想AOP起作用,就要加@EnableAspectJAutoProxy
注解,所以AOP的原理可以从该注解入手研究。它是一个复合注解,启动的时候,给容器中导入了一个AspectJAutoProxyRegistrar
组件。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {}
AspectJAutoProxyRegistrar
该类实现了ImportBeanDefinitionRegistrar
接口,而该接口的作用是给容器中注册Bean。所以AspectJAutoProxyRegistrar
作用是添加自定义组件给容器中注册Bean。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 注册了 AnnotationAwareAspectJAutoProxyCreator 组件
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
// 获取 @EnableAspectJAutoProxy 中的属性,做一些工作
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
那AspectJAutoProxyRegistrar
组件何时注册?关键代码如下:
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
该方法是给容器中注册了一个AnnotationAwareAspectJAutoProxyCreator
组件。
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
//注册或者升级AutoProxyCreator定义beanName为
// org.Springframework.aop.config.internalAutoProxyCreator的BeanDefinition
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//对于proxy-target-class以及expose-proxy属性的处理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
//注册组件并通知,便于监听器进一步处理,其中BeanDefinition的className
// 为AnnotationAwareAspectJAutoProxyCreator
registerComponentIfNecessary(beanDefinition, parserContext);
}
@EnableAspectJAutoProxy
注解最主要的作用实际上就是通过@Import
注解把AnnotationAwareAspectJAutoProxyCreator
这个对象注入到Spring容器中。现在只要把AnnotationAwareAspectJAutoProxyCreator
组件何时注册搞懂,AspectJAutoProxyRegistrar
组件何时注册也就明白了。AnnotationAwareAspectJAutoProxyCreator
继承关系:
AnnotationAwareAspectJAutoProxyCreator
extends AspectJAwareAdvisorAutoProxyCreator
extends AbstractAdvisorAutoProxyCreator
extends AbstractAutoProxyCreator
extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor,BeanFactoryAware
extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean
其中的一个父类为AbstractAutoProxyCreator
这个父类实现了SmartInstantiationAwareBeanPostProcessor
接口,该接口是一个后置处理器接口,同样实现了BeanFactoryAware
接口,这意味着,该类可以通过接口中的方法进行自动装配BeanFactory
。SmartInstantiationAwareBeanPostProcessor
、BeanFactoryAware
这两个接口在AOP体系中具体的实现方法:
AbstractAutoProxyCreator
- 重写
BeanFactoryAware
接口中的setBeanFactory
方法; - 重写
SmartInstantiationAwareBeanPostProcessor
接口中的postProcessBeforeInstantiation
和postProcessAfterInitialization
方法;
- 重写
AbstractAdvisorAutoProxyCreator
- 重写
BeanFactoryAware
接口中的setBeanFactory
方法;
- 重写
AnnotationAwareAspectJAutoProxyCreator
- 重写
BeanFactoryAware
接口中的initBeanFactory
方法;
- 重写
在重写BeanFactoryAware
接口中的initBeanFactory
方法,打断点即可看到类似下面的方法调用栈:
AnnotationConfigApplicationContext.AnnotationConfigApplicationContext()
-->AbstractApplicationContext.refresh() //刷新容器,给容器初始化bean
-->AbstractApplicationContext.finishBeanFactoryInitialization()
-->DefaultListableBeanFactory.preInstantiateSingletons()
-->AbstractBeanFactory.getBean()
-->AbstractBeanFactory.doGetBean()
-->DefaultSingletonBeanRegistry.getSingleton()
-->AbstractBeanFactory.createBean()
-->AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation()
-->AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation()
-->AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation()
-->调用AOP相关的后置处理器
其中AbstractApplicationContext.refresh()
方法,调用了registerBeanPostProcessors
方法,它是用来注册后置处理,也是在这个方法中完成了对AnnotationAwareAspectJAutoProxyCreator
的注册。注册完BeanPostProcessor
后,还调用了finishBeanFactoryInitialization
方法,完成BeanFactory
初始化工作,并创建剩下的单实例Bean。
@Override
public void refresh() throws BeansException, IllegalStateException {
// .....
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// .....
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// .....
}
下面详细的说明registerBeanPostProcessors
、finishBeanFactoryInitialization
这两个方法。
registerBeanPostProcessors
registerBeanPostProcessors
方法中注册了所有的BeanPostProcessor
,注册顺序为:
- 注册实现了
PriorityOrdered
接口的BeanPostProcessor
。 - 注册实现了
Ordered
接口的BeanPostProcessor
。 - 注册常规的
BeanPostProcessor
,也就是没有实现优先级接口的BeanPostProcessor
。 - 最后才注册
Spring
内部BeanPostProcessor
。
由于AnnotationAwareAspectJAutoProxyCreator
类间接实现了Ordered
接口,所以它是在注册实现Ordered
接口的BeanPostProcessor
中完成注册。在注册时会调用AbstractBeanFactory.getBean()
-> AbstractBeanFactory.doGetBean()
方法创建Bean。doGetBean()
方法作用为,创建Bean、给Bean中的属性赋值、初始化Bean。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// 创建 Bean 实例
Object beanInstance = createBeanInstance(mbd, beanName, args);
// 提前暴露已经创建的 Bean 实例,用于解决循环依赖问题
Object exposedObject = beanInstance;
try {
// 给 Bean 实例应用属性填充,包括依赖注入
populateBean(beanName, mbd, instanceWrapper);
// 初始化 Bean,执行各种初始化方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}catch (Exception ex) {
throw new BeanCreationException(beanName, "Initialization of bean failed", ex);
}
// 注册销毁回调,用于在 Bean 销毁时执行清理操作
registerDisposableBeanIfNecessary(beanName, exposedObject, mbd);
return exposedObject;
}
当初始化Bean时,initializeBean
方法会调用BeanPostProcessor
和BeanFactory
以及Aware
接口的相关方法,这也是BeanPostProcessor
初始化Bean的原理。
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// ...
invokeAwareMethods(beanName, bean); //处理Aware接口的方法回调
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 执行后置处理器的postProcessBeforeInitialization方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 执行自定义的初始化方法,也就是在这执行 setBeanFactory方法
invokeInitMethods(beanName, wrappedBean, mbd);
}catch (Throwable ex){
throw new BeanCreationException(beanName, "Invocation of init method failed", ex);
}
// ...
if (mbd == null || !mbd.isSynthetic()) {
// 执行后置处理器的postProcessAfterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
// ...invokeAwareMethods方法简要 ...
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
initializeBean
方法的作用为,invokeAwareMethods
方法处理Aware
接口的方法回调、执行后置处理器的postProcessBeforeInitialization
方法、执行自定义的初始化方法invokeInitMethods
、执行后置处理器的postProcessAfterInitialization
方法。initializeBean
方法执行成功,AnnotationAwareAspectJAutoProxyCreator
组件才会注册和初始化成功。
finishBeanFactoryInitialization
除了弄懂AnnotationAwareAspectJAutoProxyCreator
组件何时注册,也需要知道它什么时候被调用,这就涉及到finishBeanFactoryInitialization
方法。
AnnotationConfigApplicationContext.AnnotationConfigApplicationContext()
-->AbstractApplicationContext.refresh() // 刷新容器,给容器初始化bean
-->AbstractApplicationContext.finishBeanFactoryInitialization() // 调用
-->DefaultListableBeanFactory.preInstantiateSingletons()
-->AbstractBeanFactory.getBean()
-->AbstractBeanFactory.doGetBean()
-->DefaultSingletonBeanRegistry.getSingleton()
-->AbstractBeanFactory.createBean()
-->AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation()
-->AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation()
-->AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation()
-->调用AOP相关的后置处理器
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// ...
// 注释大意: 实例化所有剩余的(非lazy-init)单例。
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons(); // 断点停在这里
}
finishBeanFactoryInitialization
方法也需要注册Bean,它会调用preInstantiateSingletons
方法遍历获取容器中所有的Bean,实例化所有剩余的、非懒加载初始化的单例Bean。
@Override
public void preInstantiateSingletons() throws BeansException {
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 获取,非抽象、单例、非懒加载Bean
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 是否 是FactoryBean类型
if (isFactoryBean(beanName)) {
// ...
}
else {
getBean(beanName); // 断点停在这
}
}
}
// ...
}
preInstantiateSingletons()
方法通过调用getBean()
方法获取Bean实例,执行过程为:
getBean()
-->doGetBean()
-->getSingleton()
-->createBean()
又回到了上面registerBeanPostProcessors
中注册Bean的步骤。这里要注意createBean
方法中的resolveBeforeInstantiation
方法,这里可以理解为缓存Bean,如果被创建了就拿来直接用,如果没有则创建Bean。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// ...
try {
// 注释大意:给 BeanPostProcessors 一个返回代理而不是目标bean实例的机会。
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse); // 断点停在这里
if (bean != null) {
return bean;
}
}catch (Throwable ex){
// ...
}
// ...
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}catch (Throwable ex){
// ...
}
// ...
return null;
}
详细解析resolveBeforeInstantiation
方法,其中关键是调用applyBeanPostProcessorsBeforeInstantiation
方法。
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 调用 applyBeanPostProcessorsBeforeInstantiation 方法
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); // 断点停在这
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
// ... 上面代码调用的方法 ...
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
// 遍历所有的 BeanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// //如果是 InstantiationAwareBeanPostProcessor 类型
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 调用 postProcessBeforeInstantiation 方法
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); // 断点停在这
if (result != null) {
return result;
}
}
}
return null;
}
关键代码为ibp.postProcessBeforeInstantiation(beanClass, beanName)
,这里就是调用AnnotationAwareAspectJAutoProxyCreator
组件的postProcessBeforeInstantiation
方法。AnnotationAwareAspectJAutoProxyCreator
组件实现了SmartInstantiationAwareBeanPostProcessor
接口,所以bp instanceof InstantiationAwareBeanPostProcessor
这行代码为true
。
AnnotationAwareAspectJAutoProxyCreator
extends AspectJAwareAdvisorAutoProxyCreator
extends AbstractAdvisorAutoProxyCreator
extends AbstractAutoProxyCreator
extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor,BeanFactoryAware
extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean
SmartInstantiationAwareBeanPostProcessor
extends InstantiationAwareBeanPostProcessor
extends BeanPostProcessor
postProcessAfterInitialization
AOP相关的后置处理器就是在postProcessBeforeInstantiation
方法被调用的。上面的resolveBeforeInstantiation
方法是createBean
方法的调用栈,所以从层次结构上来看AnnotationAwareAspectJAutoProxyCreator
组件的调用是在创建Bean实例之前,尝试用后置处理器返回对象的。一直往父类寻找,在其父类AbstractAutoProxyCreator
实现了该方法。
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
//根据给定的bean的class和name构建出key,格式:beanClassName_beanName
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
//一个非常核心的方法:wrapIfNecessary(),如果它适合被代理,则需要封装指定的bean。
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
其有一个非常核心的方法wrapIfNecessary()
,这个方法就是代理创建的雏形。创建代理主要包含了两个步骤:获取增强方法或者增强器、根据获取的增强进行代理。
/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//如果已经处理过
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//这个bean无需增强
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//判断给定的bean是否是一个基础设施类,基础设施类不应代理,或者配置了指定bean不需要代理。
//所谓InfrastructureClass就是指Advice/PointCut/Advisor等接口的实现类。
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 如果存在增强方法则创建代理
//获取这个bean的advice
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//如果获取到了增强则需要针对增强创建代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//创建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
wrapIfNecessary
方法中调用了getAdvicesAndAdvisorsForBean
方法,该方法作用为获取增强方法或者增强器。调用栈为:
AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
-->AbstractAdvisorAutoProxyCreator.findEligibleAdvisors
-->AbstractAdvisorAutoProxyCreator.findCandidateAdvisors
-->BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans
BeanFactoryAdvisorRetrievalHelper
这个类是一个Spring AOP内部工具类,用来从Bean容器中获取所有Spring的Advisor Bean。该工具内部使用了缓存机制,虽然公开的查找方法可能会被调用多次,但并不是每次都会真正查找,而是会利用缓存。
public List<Advisor> findAdvisorBeans() {
//cachedAdvisorBeanNames是advisor名称的缓存
String[] advisorNames = this.cachedAdvisorBeanNames;
//如果cachedAdvisorBeanNames为空,则到容器中查找,并设置缓存,后续直接使用缓存即可
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
//从容器中查找Advisor类型的bean的名称
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
//遍历advisorNames
for (String name : advisorNames) {
if (isEligibleBean(name)) {
//忽略郑州创建中的advisor bean
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
//调用getBean方法从容器中获取名称为name的bean,并将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;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
if (logger.isTraceEnabled()) {
logger.trace("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;
}
}
}
}
return advisors;
}
wrapIfNecessary
方法中第二行关键的代码就是创建代理,调用了下面这行代码。
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
//步骤1:获取当前类的属性。
proxyFactory.copyFrom(this);
//步骤2:添加代理接口。
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//步骤3:拦截器封装转化为增强器
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
//步骤4:将Advisor加入到ProxyFactory中。
proxyFactory.addAdvisors(advisors);
//步骤5:设置要代理的类。
proxyFactory.setTargetSource(targetSource);
//步骤6:为子类提供了定制函数customizeProxyFactory
customizeProxyFactory(proxyFactory);
//步骤7:设置是否需要冻结代理对象。用来控制代理工厂被配置后,是否还允许修改通知。缺省值为false
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//步骤8:进行代理操作。
return proxyFactory.getProxy(getProxyClassLoader());
}
其中的关键代码是proxyFactory.getProxy(getProxyClassLoader())
,作用是代理类的创建和处理。
public Object getProxy() {
// 调用了ProxyCreatorSupport的createAopProxy()方法创建一个AopProxy对象
// 然后调用AopProxy对象的getProxy方法
return createAopProxy().getProxy();
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// 实际就是使用DefaultAopProxyFactory来创建一个代理对象
// 可以看到在调用createAopProxy方法时,传入的参数是this
// 这是因为ProxyCreatorSupport本身就保存了创建整个代理对象所需要的配置信息
return getAopProxyFactory().createAopProxy(this);
}
createAopProxy
通过AOP相关的配置信息来决定到底是使用CGLib代理还是JDK代理。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 如果开启了优化,或者ProxyTargetClass设置为true
// 或者没有提供代理类需要实现的接口,那么使用cglib代理
// 在前面分析参数的时候已经说过了
// 默认情况下Optimize都为false,也不建议设置为true,因为会进行一些侵入性的优化
// 除非你对cglib的优化非常了解,否则不建议开启
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.");
}
// 需要注意的是,如果需要代理的类本身就是一个接口
// 或者需要被代理的类本身就是一个通过jdk动态代理生成的类
// 那么不管如何设置都会使用jdk动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
// 否则都是jdk代理
else {
return new JdkDynamicAopProxy(config);
}
}
AOP原理用的就是动态代理,而且在Spring
中主要使用了两种动态代理:
- JDK动态代理技术:JDK的动态代理时基于Java的反射机制来实现的,是Java 原生的一种代理方式。他的实现原理就是让代理类和被代理类实现同一接口,代理类持有目标对象来达到方法拦截的作用。通过接口的方式有两个弊端一个就是必须保证被代理类有接口,另一个就是如果相对被代理类的方法进行代理拦截,那么就要保证这些方法都要在接口中声明。接口继承的是
java.lang.reflect.InvocationHandler
。 - CGLib动态代理技术:CGLib动态代理使用的ASM这个非常强大的Java字节码生成框架来生成
class
,基于继承的实现动态代理,可以直接通过super
关键字来调用被代理类的方法,子类可以调用父类的方法,不要求有接口。
动态代理
代理是一种常见的设计模式,通过为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介的作用,可以在不修改目标对象的情况下,扩展其功能。代理模式包含三个主要角色:代理接口、目标对象、代理对象。代理模式分为静态代理和动态代理两种类型。静态代理在编译时由程序员手动创建或通过工具生成代理类,增加了代码量。动态代理在运行时动态生成代理类,包括JDK动态代理和CGLIB动态代理。
Spring默认采取的动态代理机制实现AOP,简单来说就是在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式。JDK动态代理使用java.lang.reflect.Proxy
类和java.lang.reflect.InvocationHandler
接口来实现,它只能代理实现了接口的类。
public interface Service {
void perform();
}
public class RealService implements Service {
@Override
public void perform() {
System.out.println("Executing perform method in RealService");
}
}
public class ServiceInvocationHandler implements InvocationHandler {
private final Object target;
public ServiceInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method call");
Object result = method.invoke(target, args);
System.out.println("After method call");
return result;
}
}
public class Main {
public static void main(String[] args) {
Service realService = new RealService();
ServiceInvocationHandler handler = new ServiceInvocationHandler(realService);
Service proxyService = (Service) Proxy.newProxyInstance(
realService.getClass().getClassLoader(),
realService.getClass().getInterfaces(),
handler
);
proxyService.perform();
}
}
CGLIB动态代理使用字节码生成技术,可以代理没有实现接口的类。它通过继承的方式创建代理类,因此不能代理final
类。
<!--在pom.xml中添加以下依赖-->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
public class RealService {
public void perform() {
System.out.println("Executing perform method in RealService");
}
}
public class ServiceMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method call");
Object result = proxy.invokeSuper(obj, args);
System.out.println("After method call");
return result;
}
}
public class Main {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(RealService.class);
enhancer.setCallback(new ServiceMethodInterceptor());
RealService proxyService = (RealService) enhancer.create();
proxyService.perform();
}
}