个人理解:SpringAOP是SpringIOC的扩展功能,IOC功能返回的是Spring容器中的实际对象,而AOP功能返回的是Spring容器中实际对象的代理对象。
1.准备工作
AOP的简单使用示例:创建目录结构如下
AOP类,切面类定义如下
//切面类的专属注解
@Aspect
public class Aop {
//切点
@Pointcut("execution(public * com.njupt.springcode.aop.CalculateImp.*(..))")
public void pointCut(){}
//before通知类型
@Before(value = "pointCut()")
public void methodBefore(JoinPoint joinPoint){
System.out.println("before方法");
}
//after通知类型
@After(value = "pointCut()")
public void methodAfter(JoinPoint joinPoint){
System.out.println("after方法");
}
}
Calculate:接口类
CalculateImp类:被代理类,简单的输出操作
Main类:配置类
//配置类的注解
@Configuration
//开启AOP代理
@EnableAspectJAutoProxy
public class MainConfig {
@Bean
public CalculateImp calculateImp(){
return new CalculateImp();
}
@Bean
public Aop aop(){
return new Aop();
}
@Bean
public MyBeanPostProcessor myBeanPostProcessor(){
return new MyBeanPostProcessor();
}
}
MyBeanPostProcessor类:测试spring后置处理器设置的,springAOP就是通过spring提供的后置处理器实现为容器中的bean创建代理类的。
springAOP:启动类
运行结果
2.这个代理对象如何产生?
2.1代理对象通过AbstractAutoProxyCreator这个类产生,这个类的继承关系如下图所示:
2.2 那么这个AbstractAutoProxyCreator类是如何产生的呢?这里以注解的形式定义AOP时AbstractAutoProxyCreator类产生的时机为例。
以注解的形式定义AOP的示例如下:
//配置类的注解
@Configuration
//AOP所需的注解
@EnableAspectJAutoProxy
public class MainConfig {
//切面类
@Bean
public Aop aop(){
return new Aop();
}
//被代理类(一般的service)
@Bean
public CalculateImp calculateImp(){
return new CalculateImp();
}
}
AbstractAutoProxyCreator类产生的玄机就藏在@EnableAspectJAutoProxy注解中
@EnableAspectJAutoProxy注解的定义如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//这个元注解会创建AspectJAutoProxyRegistrar类
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
*/
boolean proxyTargetClass() default false;
/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
*/
boolean exposeProxy() default false;
}
AspectJAutoProxyRegistrar类实现了ImportBeanDefinitionRegistrar接口并覆写了registerBeanDefinitions方法
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//创建AnnotationAwareAspectJAutoProxyCreator类
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);方法如下
AnnotationAwareAspectJAutoProxyCreator类是创建代理类的顶层类
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
//将AnnotationAwareAspectJAutoProxyCreator类注入容器
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
至此,AbstractAutoProxyCreator类就产生了。
2.3 那么AbstractAutoProxyCreator类是如何工作的呢???
AbstractAutoProxyCreator类实现了Spring的扩展接口SmartInstantiationAwareBeanPostProcessor,并覆写了postProcessBeforeInstantiation(bean实例化之前的后置处理器)、postProcessAfterInitialization(bean初始化之后的后置处理器)方法。(Instantiation:实例化;Initialization初始化)。所以AbstractAutoProxyCreator类会在spring容器创建的过程中作为BeanPostProcessors注册到spring容器中,大概的方法调用栈如下:
refresh();--->registerBeanPostProcessors(beanFactory);
debug查看spring的bean工厂里的BeanPostProcessors如下图所示:
可以发现AnnotationAwareAspectJAutoProxyCreator类已经作为后置处理器被注册到了spring容器中,这个后置处理器将参与bean的创建过程,那么它是如何参与的呢?
spring创建bean大概的方法调用栈如下:
finishBeanFactoryInitialization(beanFactory);--->beanFactory.preInstantiateSingletons();(创建剩下所有的单例bean)--->getBean(beanName);(空壳方法)--->doGetBean();(获取bean,如果容器中没有,则创建bean)--->createBean(beanName, mbd, args);(创建bean,AnnotationAwareAspectJAutoProxyCreator类会在这个方法中起到作用)--->doCreateBean();,接下来看一下createBean(beanName, mbd, args);这个方法
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//省略其他代码
try {
//重点操作在这里
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//给后置处理器一个机会为创建中的bean返回一个代理类
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
}
resolveBeforeInstantiation(beanName, mbdToUse);方法
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) {
//这个方法会遍历所有的后置处理器执行它们实现的postProcessBeforeInstantiation方法(实例化之前,这个方法主要针对切面类,这里会记录切面信息)
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
//bean初始化完成之后执行的方法,创建代理对象
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
AbstractAutoProxyCreator类的postProcessBeforeInstantiation方法和postProcessAfterInitialization方法实现如下:
postProcessBeforeInstantiation方法的功能:将切面信息记录在advisorsCache(一般的AOP类)中。
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
postProcessAfterInitialization方法的功能就是创建代理对象
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
至此,spring创建bean的过程就与AbstractAutoProxyCreator类建立了联系,但记录切面信息、为目标类选择合适的通知器、创建代理对象等功能都会在AbstractAutoProxyCreator类实现,这个类才是springAOP的核心所在,所以上述只是springAOP的冰山一角。(盗一张图)
上述所说的功能可以参看以下博客的内容: