目录
1、AOP基本概念
2、AOP应用场景
3、AOP的实践
4、AOP 切面执行顺序分析
5、AOP使用注意事项
6、AOP的设计思想
7、源码解析
7.1、后置处理器AnnotationAwareAspectJAutoProxyCreator的创建
7.2、增强业务Bean的创建
7.3、调用执行阶段
8、小结
切面注解
解析注解的类信息: 注解分为 3 类: @Target({ElementType.METHOD,ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface BaseLog { } 一类是 java 自带的标准注解:包括常用的@Controller @Service @Repository 二类是元注解,元注解是用于定义注解的注解,包括 @Retention(表明注解被保留的阶段) 源代码-编译器 - 运行期 什么作用范围,生命周期? @targe(标明注解使用的范围) 什么范围使用? @Inherited(标明注解可继承) 能否被继承? @Documented(标明是否生成javadoc文档) 是否包含在javadoc中? 三类是自定义注解,根据自己的定义需求注解 注解的作用域: source:存在java代码级别,编译为class就无效了; @Override,格式检查,是否覆盖实现了接口的方法 class:编译期级别,帮我们生成get和set方法; lambook @Data Runtime类型:运行期间产生作用 @Service,很常见拦截方法
public class Calc { //业务逻辑 @BaseLog public int div(int i, int j) { return i / j; } }配置类
@Configuration @EnableAspectJAutoProxy public class ConfigAop { @Bean public Calc getCalc(){ return new Calc(); } @Bean public LogAspect getAspect(){ return new LogAspect(); } }测试类:
@Test public void aopTest() { AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(com.aop.ConfigAop.class); Calc calc = app.getBean(Calc.class); System.out.println("result: "+ calc.div(8, 2)); }正常运行结果8/2:
logAround 执行目标方法之前: Before 除法运行开始,方法名:div 参数列表: {[8, 2]} div running logAround 目标方法执行之后: After 除法运行结束。。。。 AfterReturning 除法正常返回,结果为:4 result: 4异常运行:输入2/0的结果:
logAround 执行目标方法之前: Before 除法运行开始,方法名:div 参数列表: {[2, 0]} div running java.lang.ArithmeticException: / by zero at com.enjoy.aop.aop.Calc.div(Calc.java:15) After 除法运行结束。。。。 AfterReturning 除法正常返回,结果为:-1 reslut: -1通过调试,你会发现Calc是经过增强的Bean,它其实变成了一个实现了Advised接口的代理类,并不是原生的Calc类,所以才会运行自己编写的切面类。
AOP的执行流程图如下:
思考:如果同一个方法被两个Aspect所拦截,那么它们的先后顺序怎么确定呢,关系会根据调用顺序嵌套执行? [Aspect-1] logAround 执行目标方法之前: [Aspect-1] Before 除法运行开始:div 参数列表: {[8, 2]} [Aspect-2] logAround 执行目标方法之前: [Aspect-2] Before 除法运行开始:div 参数列表: {[8, 2]} Ok [Aspect-2] logAround 目标方法执行之后: [Aspect-2] After 除法运行结束。。。。 [Aspect-2] AfterReturning 除法正常返回,结果为:4 [Aspect-1] logAround 目标方法执行之后: [Aspect-1] After 除法运行结束。。。。 [Aspect-1] AfterReturning 除法正常返回,结果为:4如果要确定两个切面的执行顺序,可以给aspect添加@Order注解,值越小优先级越高。
@Order(1) @Component @Aspect public class ParamCheckAspect1 { // ... } @Order(2) @Component @Aspect public class LogAspect2 { // ... }这样就先执行参数校验的切面ParamCheckAspect1,然后执行日志打印的切面拦截LogAspect2,控制了其执行顺序。
2、Final方法不能被通知,因为它final不能被重写,动态代理的CGlib不能重写final方法;
3、对于@Around这个注解,不管它有没有返回值,内部都必须要调用一下pjp.proceed(),否则目标方法将不会执行,也就是@Before无法执行;如果我们去掉这个执行方法,运行结果如下:
注释掉://Object obj = proceedingJoinPoint.proceed(); @Before和目标方法不会执行,运行结果: logAround 执行目标方法之前: logAround 目标方法执行之后: After 除法运行结束。。。。 AfterReturning 除法正常返回,结果为:-1 reslut: -1可以看到,结果打印没有方法的执行。
继续查看AspectAutoProxyRegistrar源码,发现其通过ImportBeanDefinitionRegistrar向容器中注入了一个十分重要的组件:AnnotationAwareAspectJAutoProxyCreator.class,它贯穿了整个aop的全过程;
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) { 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); } } } }@Nullable public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary( BeanDefinitionRegistry registry, @Nullable Object source) { //开始向容器中注入组件:AnnotationAwareAspectJAutoProxyCreator return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); } 看一下AnnotationAwareAspectJAutoProxyCreator的作用? 这里先看一下它的继承关系: public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator { public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator { public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator { public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {从这里可以看出,它是一个后置处理器;主要关注我们的bean初始化的前后需要做的事情,自动装配BeanFactory
BeanFactory : Spring容器的顶层接口,实现Bean的创建,获取,生命周期的管理等等; SmartInstantiationAwareBeanPostProcessor :Bean的后置处理器,也是一个很重要的组件,主要用来对业务方法进行Bean的代理增强;一切从容器的启动refresh开始:
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. //调用所有注册的BeanFactoryPostProcessor的Bean定义信息,但是未创建未初始化; invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. //BeanPostProcessor是Bean后置处理器的创建,用于监听容器触发的事件aop相关bean的创建,aop相关的bean就是在这里注册创建实例化; //AnnotationAwareAspectJAutoProxyCreator.class就是在这里创建实例化; registerBeanPostProcessors(beanFactory); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //相关业务bean的创建,也就是计算类calc类的创建 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } 创建剩余的保留的单实例bean: protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // Initialize conversion service for this context. if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // Instantiate all remaining (non-lazy-init) singletons. beanFactory.preInstantiateSingletons(); }继续初始化bean:
@Override public void preInstantiateSingletons() throws BeansException { String FACTORY_BEAN_PREFIX = "&"; //得到所有的bean的名字 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { final FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else {//循环获取这个bean getBean(beanName); } } } 继续getBean(): @Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); }这里主要关注 Calculator的创建,是如何增强的?
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { // Create bean instance. //创建bean实例 if (mbd.isSingleton()) { //第一次根据bean name去拿单实例bean,肯定没有 sharedInstance = getSingleton(beanName, () -> { try {//创建bean实例 return createBean(beanName, mbd, args); } }获取calculator的bean,并判断有无增强处理:
@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的前置处理器,遍历出所有的postProcessBean; Object bean = resolveBeforeInstantiation(beanName, mbdToUse); //第一步:创建一个单实例bean;普通的实例bean if (bean != null) { return bean; } } try { //第二步:后置处理器返回一个动态代理 Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } @Nullable //初始化之前判断是否有后置处理器的增强; 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. //判断该bean Calcutor是否是实现了BeanPostProcessor,显然满足条件是一个后置处理,加了aop的功能 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { //前置处理器 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { //后置处理器 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean; } // 找到Calcutor的后置处理器 AnnotationAwareAspectJAutoProxyCreator 进行增强; //前置处理器主要是 拿到@Aspect中的所有切面方法 public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) { //拿到bean的名字,cachekey ==Calcutor Object cacheKey = getCacheKey(beanClass, beanName); TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } //找到 Calcutor 的增强器,主要是拦截的4个切面类 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; //至此-返回一个代理对象,但是before不会产生任何代理 } } //找 Calcutor的增强器 protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); //获取合适的增强器,就是我们编写的before - after - around的切面类 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { //对增强器进行排序,因为方法调用是有时机顺序的,前面也提到验证过,before-after-return eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }通过反射创建一个增强的代理bean,最后生成的这个Bean就是加入切面类增强的Bean。
*/ protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } // 第一步:通过反射创建bean if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } Object exposedObject = bean; try { //第二步:给实例bean赋值 populateBean(beanName, mbd, instanceWrapper); //第三步:给bean初始化 exposedObject = initializeBean(beanName, exposedObject, mbd); }进入到后置处理器:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) {//初始化前置处理器 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { //调用方法 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()) {//初始化后置处理器 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }进入后置处理器,后置处理器的作用:
拿到所有的通知方法; 创建增强的动态代理对象;Calcutor对象; @Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { //从缓存中拿到bean的名字 Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }如果对象有增强,找到增强器,因为切面类不是实现的接口,所以开始通过Cglib创建代理对象:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { // Create proxy if we have advice. //先获取排好序的通知类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; } //创建动态代理类,创建aop增强bean的创建 public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { 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."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { //方式一:如果有接口,就使用 jdk动态代理; return new JdkDynamicAopProxy(config); } //方式二:如果没有接口,就使用CGLib动态代理 return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } } }至此,我们的增强bean Calc就创建完成了。
获取拦截链的拦截通知方法,也就是Aspect中写的拦截方法,这里获取到:
@Override//拿到所有的通知方法 public List<Object> getInterceptorsAndDynamicInterceptionAdvice( Advised config, Method method, @Nullable Class<?> targetClass) { // This is somewhat tricky... We have to process introductions first, // but we need to preserve order in the ultimate list. AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); Advisor[] advisors = config.getAdvisors(); //第一步:拿到通知方法的长度 List<Object> interceptorList = new ArrayList<>(advisors.length); Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass()); Boolean hasIntroductions = null; for (Advisor advisor : advisors) { if (advisor instanceof PointcutAdvisor) { // Add it conditionally. if (mm instanceof IntroductionAwareMethodMatcher) { if (hasIntroductions == null) { hasIntroductions = hasMatchingIntroductions(advisors, actualClass); } if (match) { //第二步:将Inteceptor转换为MethodInterceptor MethodInterceptor[] interceptors = registry.getInterceptors(advisor); if (mm.isRuntime()) { // Creating a new object instance in the getInterceptors() method // isn't a problem as we normally cache created chains. for (MethodInterceptor interceptor : interceptors) { interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm)); } } return interceptorList; } 栈式调用我们具体通知方法: @Override @Nullable public Object proceed() throws Throwable { // We start with an index of -1 and increment early. //第一步:通过i++来取我们的通知拦截方法 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 { // It's an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. //第二步:栈式方法调用 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }到此,我们创建和执行阶段就完全解析完了。虽然搞了好久,不过好似打通了任督二脉,舒坦。