Spring AOP概念理解
Aspect(切面):AOP基本单元,类似于面向对象基本单元是类
Joinpoint(连接点):方法执行点
Advice:切点处执行的逻辑(增强处理)
很多时候你不知不觉就使用了AOP:在@Component类中,你在方法上加了@Transactional注解之后,方法执行前会开始事务,方法执行之后结束事务,方法发生异常之后回退事务;加上@Async注解之后,方法最终被调用的时候是异步的;加上@Cacheable注解之后,方法的返回值会被缓存起来,下次调用的时候直接返回缓存值。这些都是框架提供给你的,你只要加个注解声明一下就能用。
同时你也可以编写AOP代码来实现自己需求,比如在方法执行之前开始计时,在方法结束之后停止计时,来得到方法的运行时间;比如在业务的关键地方加上log;比如权限控制、懒加载等等。使用AOP的特点就是侵入性比较小,你的业务代码不用动,降低耦合度,方便团队分工。
Advisor是什么
Spring AOP范畴概念
package org.springframework.aop;
import org.aopalliance.aop.Advice;
/**
* Base interface holding AOP <b>advice</b> (action to take at a joinpoint)
* and a filter determining the applicability of the advice (such as
* a pointcut). <i>This interface is not for use by Spring users, but to
* allow for commonality in support for different types of advice.</i>
*
* <p>Spring AOP is based around <b>around advice</b> delivered via method
* <b>interception</b>, compliant with the AOP Alliance interception API.
* The Advisor interface allows support for different types of advice,
* such as <b>before</b> and <b>after</b> advice, which need not be
* implemented using interception.
*
* @author Rod Johnson
* @author Juergen Hoeller
*/
public interface Advisor {
/**
* Common placeholder for an empty {@code Advice} to be returned from
* {@link #getAdvice()} if no proper advice has been configured (yet).
* @since 5.0
*/
Advice EMPTY_ADVICE = new Advice() {};
/**
* Return the advice part of this aspect. An advice may be an
* interceptor, a before advice, a throws advice, etc.
* @return the advice that should apply if the pointcut matches
* @see org.aopalliance.intercept.MethodInterceptor
* @see BeforeAdvice
* @see ThrowsAdvice
* @see AfterReturningAdvice
*/
Advice getAdvice();
/**
* Return whether this advice is associated with a particular instance
* (for example, creating a mixin) or shared with all instances of
* the advised class obtained from the same Spring bean factory.
* <p><b>Note that this method is not currently used by the framework.</b>
* Typical Advisor implementations always return {@code true}.
* Use singleton/prototype bean definitions or appropriate programmatic
* proxy creation to ensure that Advisors have the correct lifecycle model.
* @return whether this advice is associated with a particular target instance
*/
boolean isPerInstance();
}
Intercepter
接口继承自Advice,以事务拦截器TransactionInterceptor说明
MethodInvocation
ReflectiveMethodInvocation
InvocationHandler
Java 反射中概念
package java.lang.reflect;
/**
* {@code InvocationHandler} is the interface implemented by
* the <i>invocation handler</i> of a proxy instance.
*
* <p>Each proxy instance has an associated invocation handler.
* When a method is invoked on a proxy instance, the method
* invocation is encoded and dispatched to the {@code invoke}
* method of its invocation handler.
*
* @author Peter Jones
* @see Proxy
* @since 1.3
*/
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
Spring AOP 处理过程
1.@EnableAspectJAutoProxy注解会开启AOP功能
2.具体过程@EnableAspectJAutoProxy 会给IOC容器中注册一个组件 AnnotationAwareAspectJAutoProxyCreator
3.AnnotationAwareAspectJAutoProxyCreator我们一直往上扒其父类会发现,它是一个后置处理器
4.然后在IOC容器创建过程中会有个registerBeanPostProcessors方法用来注册后置处理器,创建AnnotationAwareAspectJAutoProxyCreator对象
5.注册完后,IOC创建过程中还有另一个方法finishBeanFactoryInitialization(),它的作用是初始化剩下的单实例bean(省略了很多步骤)
6.在这个方法里,AnnotationAwareAspectJAutoProxyCreator会拦截bean的创建过程,去判断业务bean是不是要增强?(是不是切点)
7.是的话,就会包装增强器(Advisor),给业务bean创建一个代理对象(cglib)(我们今天不聊jdk代理)
8.然后等这个IOC容器创建完成,真正执行方法是时候,去执行方法的就是cglib代理对象
9.这个代理对象里面保存了详细信息(比如增强器,目标对象,等等),最后的执行者是CglibAopProxy.DynamicAdvisedInterceptor.intercept()
10.它会得到目标方法的拦截器链(增强器包装成拦截器MethodInterceptor)
11.利用拦截器的链式机制,依次进入每一个拦截器进行执行:
https://blog.csdn.net/aaa_bbb...
Spring创建代理对象
Spring代理对象生成入口在AbstractAutowireCapableBeanFactory#initializeBean方法,Bean在完成实例化、属性填充和初始化处理之后,通过调用Bean后置处理器(AnnotationAwareAspectJAutoProxyCreator)创建代理对象
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
} else {
//调用Bean定制实现的XXXAware接口方法
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 调用Bean初始化前的后置处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// Bean初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 调用Bean初始化后的后置处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
Proxy对象创建—> AnnotationAwareAspectJAutoProxyCreator.class(实现了BeanPostProcessor)
AbstractAutoProxyCreator#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;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 获取方法拦截器(Advisor集合),如果Advisor不为空创建代理对象
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;
}
查找Advisor方法
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = this.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!
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
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;
}
Spring Aop创建代理对象并织入切面逻辑的入口方法是AbstractAutoProxyCreator#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);
}
// 创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 将需要织入的切面逻辑都转换为Advisor对象
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
// 提供的hook方法,供子类实现以实现对代理工厂的定制
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 生成代理类
return proxyFactory.getProxy(getProxyClassLoader());
}
public Object getProxy(@Nullable ClassLoader classLoader) {
// 首先获取AopProxy对象,其主要有两个实现:JdkDynamicAopProxy和ObjenesisCglibAopProxy,
// 分别用于Jdk和Cglib代理类的生成,其getProxy()方法则用于获取具体的代理对象
return createAopProxy().getProxy(classLoader);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 判断当前类是否需要进行运行时优化,或者是指定了使用Cglib代理的方式,再或者是目标类没有用户提供的
// 相关接口,则使用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);
}
// 返回Cglib代理织入类对象
return new ObjenesisCglibAopProxy(config);
} else {
// 返回Jdk代理织入类对象
return new JdkDynamicAopProxy(config);
}
}
以下主要分析使用Cglib方式生成代理实现代理逻辑的织入
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is "
+ this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null,
"Target class must be available for creating a CGLIB proxy");
// 判断当前类是否是已经通过Cglib代理生成的类,如果是的,则获取其原始父类,
// 并将其接口设置到需要代理的接口中
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
// 获取父类
proxySuperClass = rootClass.getSuperclass();
// 获取父类实现的接口,并将其设置到需要代理的接口中
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// 对目标类进行检查,主要检查点有三个:
// 1. 目标方法不能使用final修饰;
// 2. 目标方法不能是private类型的;
// 3. 目标方法不能是包访问权限的;
// 这三个点满足任何一个,当前方法就不能被代理,此时该方法就会被略过
validateClassIfNecessary(proxySuperClass, classLoader);
// 创建Enhancer对象,并且设置ClassLoader
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
// 这里AopProxyUtils.completeProxiedInterfaces()方法的主要目的是为要生成的代理类
// 增加SpringProxy,Advised,DecoratingProxy三个需要实现的接口。这里三个接口的作用如下:
// 1. SpringProxy:是一个空接口,用于标记当前生成的代理类是Spring生成的代理类;
// 2. Advised:Spring生成代理类所使用的属性都保存在该接口中,
// 包括Advisor,Advice和其他相关属性;
// 3. DecoratingProxy:该接口用于获取当前代理对象所代理的目标对象的Class类型。
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new
ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
// 获取当前需要织入到代理类中的逻辑
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// 设置代理类中各个方法将要使用的切面逻辑,这里ProxyCallbackFilter.accept()方法返回
// 的整型值正好一一对应上面Callback数组中各个切面逻辑的下标,也就是说这里的CallbackFilter
// 的作用正好指定了代理类中各个方法将要使用Callback数组中的哪个或哪几个切面逻辑
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap,
this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// 生成代理对象
return createProxyClassAndInstance(enhancer, callbacks);
} catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class ["
+ this.advised.getTargetClass() + "]: Common causes of this problem "
+ "include using a final class or a non-visible class", ex);
} catch (Throwable ex) {
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
Spring AOP可能遇到的问题
https://www.liaoxuefeng.com/w...
springboot默认cglib
springboot 为什么将默认的代理改成了cglib,这会导致什么问题?如果我们想要事务走JDK动态代理,该如何做?
springboot团队之所以默认的代理模式设置成cglib代理,看看spring的官方团队是怎么解释的
This was changed in 1.4 (see 5423). We’ve generally found cglib proxies less likely to cause unexpected cast exceptions.
他们认为使用cglib更不容易出现转换错误。springboot 默认的配置文件的位置在
/org/springframework/boot/spring-boot-autoconfigure/2.1.7.RELEASE/spring-boot-autoconfigure-2.1.7.RELEASE.jar!/META-INF/spring-configuration-metadata.json
{
"name": "spring.aop.proxy-target-class",
"type": "java.lang.Boolean",
"description": "Whether subclass-based (CGLIB) proxies are to be created (true), as opposed to standard Java interface-based proxies (false).",
"defaultValue": true
},
如果偏要springboot 走JDK动态代理,那么需要在application.properties里面配置
spring.aop.proxy-target-class=false
Cglib代理FastClass机制
https://www.cnblogs.com/monke...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。