Spring AOP初始化及执行过程
程序员文章站
2022-03-10 08:37:18
背景当对不同的没有继承关系的对象引入一些公共的行为,比如记录日志,校验安全等,需要编写重复的代码,对一个系统的可维护性来说是非常不友好的,于是,引入了面向切面编程AOP不同于面向对象编程所关注的纵向编程,AOP所关注的是横向编程,为不同的对象方法织入切面切点 Point决定通知作用于哪些连接点通知 Advice决定在连接点做什么,为切面增强提供织入接口通知器 Advisor用于结合Point和AdviceSpring AOP 使用aspectj支持AOP在xml...
背景
- 当对不同的没有继承关系的对象引入一些公共的行为,比如记录日志,校验安全等,需要编写重复的代码,对一个系统的可维护性来说是非常不友好的,于是,引入了面向切面编程AOP
- 不同于面向对象编程所关注的纵向编程,AOP所关注的是横向编程,为不同的对象方法织入切面
- 切点 Point
- 决定通知作用于哪些连接点
- 通知 Advice
- 决定在连接点做什么,为切面增强提供织入接口
- 通知器 Advisor
- 用于结合Point和Advice
Spring AOP 使用aspectj支持AOP
- 在xml开启AOP功能,并声明AOP Bean
<aop:aspectj-autoproxy/>
<bean id="testPrintln" class="com.example.springtest.TestPrintln"></bean>
<bean class="com.example.springtest.AspectTest"/>
- 强制使用CGLIB代理
- <aop:aspectj-autoproxy proxy-target-class=“true”/>
- 在目标对象内自我调用,实现增强
- <aop:aspectj-autoproxy expose-proxy=“true”/>
- (Aservice(AopContext.currentProxy())).b()
- 注解方式开启
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@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;
}
- 定义切面 切点Pointcut为* *.test(…)) 匹配的所有连接点的集合
- @Before(“test()”) 为 增强器
@Aspect
public class AspectTest {
@Pointcut("execution(* *.test(..))")
public void test() {
}
@Before("test()")
public void before() {
System.out.println("AspectTest before");
}
@Around("test()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) {
Object result = null;
try {
System.out.println("around before");
result = proceedingJoinPoint.proceed();
System.out.println("around after");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return result;
}
@After("test()")
public void after() {
System.out.println("AspectTest after");
}
@AfterReturning("test()")
public void afterReturning() {
System.out.println("AspectTest afterReturning");
}
@AfterThrowing("test()")
public void afterAfterThrowing() {
System.out.println("AspectTest afterThrowing");
}
}
- 定义要切入的类
public class TestPrintln implements Printlnable{
@Override
public void test(){
System.out.println("我是连接点");
}
}
- 执行结果
around before
before
我是连接点
afterReturning
after
around after
动态AOP自定义标签
- AopNamespaceHadnler 用于支持AOP标签,最终注册为BeanDefinition,并放入到容器这中
public class AopNamespaceHandler extends NamespaceHandlerSupport {
/**
* Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
* '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
* and '{@code scoped-proxy}' tags.
*/
@Override
public void init() {
// In 2.0 XSD as well as in 2.1 XSD.
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
// 支持启动spring aop
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace as of 2.1
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
AnnotationAwareAspectJAutoProxyCreator 实现AOP功能
- 它可以根据@Pointcut注解定义的切点来自动代理匹配的Bean
- 继承了BeanPostProcessor,执行bean初始化后置处理器 postProcessAfterInitialization方法 返回代理Bean
- 在父类AbstractAutoProxyCreator中调用postProcessAfterInitialization方法中返回代理Bean
@Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return 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;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//如果是基础设施的类 Advice Pointcut 等 或 需要跳过
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//获取增强器
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;
}
- getAdvicesAndAdvisorsForBean 获取指定Bean的增强器
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
//获取增强器
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
- findEligibleAdvisors 获取指定Bean的增强器
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//查找所有增强器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//获取当前Bean使用的增强器
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//根据Order排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
- findCandidateAdvisors 获取所有增强器
@Override
protected List<Advisor> findCandidateAdvisors() {
//查找通过编程方式的增强器.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
//查找通过注解方式定义的增强器 @Before @Around @After定义的方法
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
- createProxy 创建代理
/**
* Create an AOP proxy for the given bean.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @param specificInterceptors the set of interceptors that is
* specific to this bean (may be empty, but not null)
* @param targetSource the TargetSource for the proxy,
* already pre-configured to access the bean
* @return the AOP proxy for the bean
* @see #buildAdvisors
*/
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();
//根据ProxyConfig获取配置
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
//判断是否强制使用CGLIB代理
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
//动态判断使用JDK 还是 CGLIB
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//从容器获取根据interceptorNames配置的增强器
//对于MethodInterceptor 、AdvisorAdapter支持的Advice 使用DefaultPointcutAdvisor包装
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
//添加增强器
proxyFactory.addAdvisors(advisors);
//添加需要代理的目标对象
proxyFactory.setTargetSource(targetSource);
//空方法 留给子类覆盖
customizeProxyFactory(proxyFactory);
//配置是否可以修改advice
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//生成代理类
return proxyFactory.getProxy(getProxyClassLoader());
}
JdkDynamicAopProxy 实现JDK动态代理
- 继承InvocationHandler
- 调用方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
- 通过ReflectiveMethodInvocation执行拦截器链
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
//非从接口继承的 且 方法为 equals
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
//设置了exposeProxy属性 将代理类放入到ThreadLocal
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
// 获取method和targetClass的拦截器(advice)调用链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 创建拦截器调用链的执行器
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
//开始执行
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
ReflectiveMethodInvocation 执行拦截器链
public Object proceed() throws Throwable {
// 判断调用链结束是否结束 ,是否已经调用到最后一个
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//执行连接点的方法 即被代理的方法
return invokeJoinpoint();
}
//取下一个拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// 继续调用拦截器
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
拦截器 MethodInterceptor
-
继承关系
-
拦截器分类
- 如果Advice的实现类没有继承MethodInterceptor需要通过适配器转化为对应的拦截器
-
AspectJAroundAdvice
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null);
}
- MethodBeforeAdviceInterceptor
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @param advice the MethodBeforeAdvice to wrap
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
//执行增强逻辑
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
//进行下一个拦截器
return mi.proceed();
}
}
- AspectJAfterAdvice
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
- AspectJAfterThrowingAdvice
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
- AfterReturningAdviceInterceptor
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
拦截器链执行时序图
本文地址:https://blog.csdn.net/piexie8364/article/details/112251484
上一篇: 《剑指offer》算法题整理