spring之AOP
- 代码使用
- 源码
- 入口
- context.getBean(xxx.class)
- 1.查看getBeanFactory方法获取到的factory是什么
- 2.查看getBeanFactory.getBean()的源码
- resolveBean()
- resolveNamedBean()
- doCreateBean()
- BeanWrapper
- 完成aop的代码
- initializeBean()
- applyBeanPostProcessorsAfterInitialization()实现了aop代理
- AnnotationAwareAspectJAutoProxyCreator
- wrapIfNecessary
- createProxy 创建代理对象
- getProxy
- createAopProxy
- createAopProxy
- AopProxy
- 为什么需要这个注解@EnableAspectJAutoProxy(proxyTargetClass = true)
- BeanPostProcessor
- 面试题
代码使用
package com.kcwl.klj.aspect;
@Aspect //切面
@Component
@Slf4j
public class LogAspect {
@Resource
private KcwlSysLogServiceImpl kcwlSysLogService;
//切点,切点里面写的是连接点的表达式
// aop要作用到哪些方法上去呢?在下行的括号中进行描述,括号中的就是连接点,连接点的集合就是切点
//可以这样理解:括号中的是连接点的表达式,该表达式会指向多个方法或者类,这些都是一条一条的数据,
// 切点这个@PointCut是一张表,表中记录了多行数据
@Pointcut("@annotation(com.kcwl.klj.annotation.OptLog)")
public void aspectLog() {
}
//AfterReturning 表示在aspectLog()的这些连接点返回之后打印aop
@AfterReturning("aspectLog()")
public void insertLog(JoinPoint joinPoint) {
//从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//获取切入点所在的方法
Method method = signature.getMethod();
//获取操作
OptLog optLog = method.getAnnotation(OptLog.class);
}
}
源码
入口
public class SpringMain {
public static void main(String[] args) {
//初始化spring容器 在初始化的时候完成了依赖注入
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringTest.class);
//下面这样代码我们需要注意,在getBean去get IndexService这个bean之前,上面的那样代码已经get过一次IndexService这个bean了。
//但是上面那行代码主要作用是初始化所有的bean,为什么还会执行get bean的方法呢?因为那行代码中要执行create 去创建bean的方法,在执行create之前需要先get一下判断是否已经创建完成这个bean
System.out.println(context.getBean(IndexService.class));
}
}
context.getBean(xxx.class)
1.查看getBeanFactory方法获取到的factory是什么
this.beanFactory则是指当前类的beanFactory属性,即下图中的属性,即DefaultListableBeanFactory
2.查看getBeanFactory.getBean()的源码
resolveBean()
@Nullable
private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
//NamedBeanHolder 可以理解为数据结构和map差不多,里面存了bean的名字和bean的实例
//resolveNamedBean(xxxxx)该方法里面就已经实现了对bean的代理
NamedBeanHolder<T> namedBean = this.resolveNamedBean(requiredType, args, nonUniqueAsNull);
if (namedBean != null) {
return namedBean.getBeanInstance();
} else {
BeanFactory parent = this.getParentBeanFactory();
if (parent instanceof DefaultListableBeanFactory) {
return ((DefaultListableBeanFactory)parent).resolveBean(requiredType, args, nonUniqueAsNull);
} else if (parent != null) {
ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType);
if (args != null) {
return parentProvider.getObject(args);
} else {
return nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable();
}
} else {
return null;
}
}
}
resolveNamedBean()
@Nullable
private <T> NamedBeanHolder<T> resolveNamedBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
//根据bean的类型获取bean
String[] candidateNames = this.getBeanNamesForType(requiredType);
String[] var6;
int var7;
int var8;
String beanName;
//如果数组的长度大于1,说明获取到了这个类型的bean有多个
if (candidateNames.length > 1) {
List<String> autowireCandidates = new ArrayList(candidateNames.length);
var6 = candidateNames;
var7 = candidateNames.length;
for(var8 = 0; var8 < var7; ++var8) {
beanName = var6[var8];
if (!this.containsBeanDefinition(beanName) || this.getBeanDefinition(beanName).isAutowireCandidate()) {
autowireCandidates.add(beanName);
}
}
if (!autowireCandidates.isEmpty()) {
candidateNames = StringUtils.toStringArray(autowireCandidates);
}
}
//如果数组的长度等于1,说明该类型的bean只有1个,而且我们获取到了,那我们就将他封装为NamedBeanHolder返回,结束当前方法
if (candidateNames.length == 1) {
String beanName = candidateNames[0];
//下面这行代码中的this.getBean(beanName, requiredType.toClass(), args)这个方法才是真正获取bean的方法
return new NamedBeanHolder(beanName, this.getBean(beanName, requiredType.toClass(), args));
} else {
//否则如果长度大于1,则走下面的逻辑
if (candidateNames.length > 1) {
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
}
return null;
}
}
上面代码中的this.getBean(beanName, requiredType.toClass(), args)方法最终走到了这儿
上图中的doGetBean中的第一行代码如下:这行代码的作用是什么?
String beanName = this.transformedBeanName(name);
通过name获取beanName,这里不使用name直接作为beanName的原因有两点:
1.name可能会以&字符开头,表明调用者想获取factoryBean本身,而不是获取factoryBean实现类所创建的bean。在BeanFactory中,factoryBean的实现类和其他bean的存储方式是一致的,即<beanName,bean>,beanName中是没有&字符的。所以我们需要将name的首字符&移除,这样才能从缓存中获取到FactoryBean实例。
2.还是别名的问题,转换需要
接下来,执行了this.getSingleton(beanName)方法,该方法是去三个map中获取bean,此时拿出来的bean就已经是代理过的bean了。
说明什么?
说明在AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringTest.class);这样代码中就已经完成了代理并将代理后的bean放在了单例池中。
现在我们找一下在哪一步往单例池中放bean了
通过搜索我们可以看到下面的情况
找到了put bean的地方
我们继续往上找
最终发现是在createBean方法中将对象创建为代理对象的
在该方法中有一行代码如下
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
该行代码实现了bean的创建,注意,如果只是创建bean则会将bean创建出来,如果该bean是被aop了,则会创建bean和这个bean的代理对象bean。
doCreateBean()
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
//BeanWrapper相当于是bean的包装类 类似于有一个A类,类里面有一个Object B = new Object(),bean就是里面的B。我们通过BeanWrapper 的其他方法可以获取到B这个属性,就可以获取到bean了
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
//下面这行方法就是使用BeanWrapper获取到里面的B这个属性,就是bean这个原身属性
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
synchronized(mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable var17) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
}
mbd.postProcessed = true;
}
}
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
//将bean赋值给了exposedObject这个对象
Object exposedObject = bean;
try {
//设置属性,非常重要
this.populateBean(beanName, mbd, instanceWrapper);
//执行后置处理器,aop就是在这里完成的处理 执行完这行代码之后,exposedObject中的bean的属性值就变成了代理的bean了
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
if (earlySingletonExposure) {
Object earlySingletonReference = this.getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
String[] dependentBeans = this.getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
String[] var12 = dependentBeans;
int var13 = dependentBeans.length;
for(int var14 = 0; var14 < var13; ++var14) {
String dependentBean = var12[var14];
if (!this.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.");
}
}
}
}
try {
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}
BeanWrapper
public interface BeanWrapper extends ConfigurablePropertyAccessor {
void setAutoGrowCollectionLimit(int var1);
int getAutoGrowCollectionLimit();
---------------------BeanWrapper的重要的两个方法------------------------------------
Object getWrappedInstance();
Class<?> getWrappedClass();
----------------------BeanWrapper的重要的两个方法-----------------------------------
PropertyDescriptor[] getPropertyDescriptors();
PropertyDescriptor getPropertyDescriptor(String var1) throws InvalidPropertyException;
}
完成aop的代码
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
initializeBean()
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
this.invokeAwareMethods(beanName, bean);
return null;
}, this.getAccessControlContext());
} else {
this.invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//第七次执行后置处理器,执行后置处理的before
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
//执行bean的 生命周期回调中的init 例如 @PostConstruct
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
//执行第八次后置处理器,执行后置处理器的after方法
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
applyBeanPostProcessorsAfterInitialization()实现了aop代理
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Object current;
for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
BeanPostProcessor processor = (BeanPostProcessor)var4.next();
current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
}
return result;
}
AnnotationAwareAspectJAutoProxyCreator
当BeanPostProcessor 为AnnotationAwareBeanPostProcessor的时候,current变成了代理bean
走进这个后置处理器的postProcessAfterInitialization方法
该后置处理器继承了AbstractAutoProxyCreator这个抽象父类,走的是父类的postProcessAfterInitialization这个方法
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//通过该行代码实现了代理bean的创建
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
createProxy 创建代理对象
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);
}
//创建了一个代理工厂factory
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (this.shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
this.evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
this.customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (this.advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(this.getProxyClassLoader());
}
this.getProxyClassLoader()这行代码的作用是什么?
为了动态加载类
我们最开始的target类是被classloader所加载的,但是如果创建代理对象的话,该代理对象proxy是没有被classloader所加载的,因此需要一个代理对象的classloader。
getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
return this.createAopProxy().getProxy(classLoader);
}
createAopProxy
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
this.activate();
}
//获取aop代理工厂,调用工厂的创建aop代理的方法去创建代理对象
return this.getAopProxyFactory().createAopProxy(this);
}
createAopProxy
下面为createAopProxy方法所在的类的全部代码
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
public DefaultAopProxyFactory() {
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//config.isOptimize() 恒定返回false
//config.isProxyTargetClass()获取的是注解:@EnableAspectJAutoProxy(proxyTargetClass = true)中的true还是false,默认是false
//this.hasNoUserSuppliedProxyInterfaces(config) 恒定为false
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
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.");
} else {
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return ifcs.length == 0 || ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0]);
}
}
AopProxy
是一个接口
public interface AopProxy {
Object getProxy();
Object getProxy(@Nullable ClassLoader var1);
}
为什么需要这个注解@EnableAspectJAutoProxy(proxyTargetClass = true)
在创建proxy代理工厂的时候,源码中会获取该注解上的proxyTargetClass的值,如果是false,则直接创建了JdkDynamicAopProxy -----jdk的动态代理。
如果为true,则判断如果target不是接口,当前target也不是代理类型的类的话,就创建ObjenesisCglibAopProxy,反之则创建JdkDynamicAopProxy。
JdkDynamicAopProxy jdk动态代理代理对象的方法
Proxy.newProxyInstance()
该方法已经是jdk的底层源码了
BeanPostProcessor
是一个接口,有非常多的类实现了这个接口
我们也可以自己写一个类实现该接口,重写里面的方法,就可以实现对bean的改造
面试题
aop和springaop有什么区别?
aop:编程目标。面向切面编程
springaop:实现目标的手段。除此之外AspectJ,手写一个JDK动态代理也可以实现aop
spring在2.5之前有自己的aop,但是非常复杂,于是借助了aspectj的语法完成了springaop的编程
aop的概念
aspect:切面
join point:连接点。比如我们添加了@A注解的方法要实现aop里的逻辑,那么被添加了@A注解的那些方法,每个方法都是一个连接点。
advice:通知
point cut:切点(连接点的集合)。一个连接点是一个方法,所有的方法加起来就是切点。
target:目标对象
weaving:织入。 A类中的a方法被加上了注解要实现aop,那么a就是连接点,A就是目标对象,advice通知A目标对象的过程就是织入。
proxy:代理
introduction:引入
springAop默认是什么代理?
可配置的,spring底层没有默认的配置,会看我们的机制是什么就用什么代理
@ComponentScan("com.guo.admin.web.spring")
@EnableAspectJAutoProxy(proxyTargetClass = true)//true则使用cglib代理
public class SpringTest {
}
如果这一行代码没有配置的话,则如果是实现了接口,则使用jdk动态代理,如果没有实现接口,则使用cglib代理
AOP五种通知
before在连接点前面执行,前置通知不会影响连接点的执行,除非此处抛出异常。
after在连接点执行完成后执行,不管是正常执行完成,还是抛出异常,都会执行返回通知中的内容。
after returning在连接点正常执行完成后执行,如果连接点抛出异常,则不会执行。
after throwing 连接点抛出异常后执行。
around环绕通知围绕在连接点前后,比如一个方法调用的前后。