美文网首页
spring aop和AspectJ的区别

spring aop和AspectJ的区别

作者: 7d972d5e05e8 | 来源:发表于2019-10-04 08:14 被阅读0次

    原文:https://www.zhoujunwen.com/2018/aop-aspectj-springaop

    AOP的代理类的创建在,doCreateBean方法中的initializeBean()。该方法主要是调用所有实现了BeanPostProcessor类的后处理器。

    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 {
                invokeAwareMethods(beanName, bean);
            }
    
            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;
        }
    

    在方法applyBeanPostProcessorsAfterInitialization中,

    @Override
        public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
                throws BeansException {
    
            Object result = existingBean;
            for (BeanPostProcessor processor : getBeanPostProcessors()) {
                Object current = processor.postProcessAfterInitialization(result, beanName);
                if (current == null) {
                    return result;
                }
                result = current;
            }
            return result;
        }
    

    BeanPostProcessor中的一个实现类,AnnotationaWAREaspectJAutoProxyCreatore类,执行了postProcessAfterInitialization方法,实现了动态代理。

    二、什么是AspectJ?

    引用文章:https://segmentfault.com/a/1190000015262333

    在网上一搜一大片所谓AspectJ的用法,其实都是AspectJ的“切面语法”,只是AspectJ框架的冰山一角,AspectJ是完全独立于Spring存在的一个Eclipse发起的项目,官方关于AspectJ的描述是:

    Eclipse AspectJ is a seamless aspect-oriented extension to the Java™ programming language. It is Java platform compatible easy to learn and use.
    是的AspectJ甚至可以说是一门独立的语言,我们常看到的在spring中用的@Aspect注解只不过是Spring2.0以后使用了AspectJ的风格而已本质上还是Spring的原生实现,关于这点Spring的手册中有提及:

    @AspectJ使用了Java 5的注解,可以将切面声明为普通的Java类。@AspectJ样式在AspectJ 5发布的AspectJ project部分中被引入。Spring 2.0使用了和AspectJ 5一样的注解,并使用AspectJ来做切入点解析和匹配。但是,AOP在运行时仍旧是纯的Spring AOP,并不依赖于AspectJ的编译器或者织入器(weaver)。

    so 我们常用的org.aspectj.lang.annotation包下的AspectJ相关注解只是使用了AspectJ的样式,至于全套的AspectJ以及织入器,那完全是另一套独立的东西。

    总结:
    1. 原生的aspectJ,其实是静态代理。它有自己的一套编译器,通过命令:

    ajc -d . Hello.java TxAspect.aj

    实现了在编译阶段生成代理类

    1. spring中的@AspectJ,本质上使用的还是动态代理。它的实现类AspectJAwareAdvisorAutoProxyCreator继承了AbstractAutoProxyCreator。该类是spring的aop包,和aspectJ一点都不沾边。@AspectJ注解,实现代理的源码如下:
                Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
                Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
    

    createProxy方法实现,还是使用了JDK或者cglib来实现的动态代理。

    以后再说两者的区别,一定要区分是AspectJ原生,还是@AspectJ注解。

    引用网上的一句话:

    Spring AOP
    spring aop常被人诟病复杂,难用。但又有多少新司机真正的用过而不是上来就被@Aspectj那一套洗脑了,问你为什么spring aop难用,AspectJ的优势在哪又有多少人能答上来。
    其实@AspectJ就是换了一个壳的Spring AOP而已

    相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,
    而Spring AOP则无需特定的编译器处理。

    二、原生AspectJ的原理

    (1)原理
    AspectJ 意思就是Java的Aspect,Java的AOP。它的核心是ajc(编译器 aspectjtools)和 weaver(织入器 aspectjweaver)。

    ajc编译器:基于Java编译器之上的,它是用来编译.aj文件,aspectj在Java编译器的基础上增加了一些它自己的关键字和方法。因此,ajc也可以编译Java代码。

    weaver织入器:为了在java编译器上使用AspectJ而不依赖于Ajc编译器,aspectJ 5出现了 @AspectJ,使用注释的方式编写AspectJ代码,可以在任何Java编译器上使用。
    由于AndroidStudio默认是没有ajc编译器的,所以在Android中使用@AspectJ来编写。它在代码的编译期间扫描目标程序,根据切点(PointCut)匹配,将开发者编写的Aspect程序编织(Weave)到目标程序的.class文件中,对目标程序作了重构(重构单位是JoinPoint),目的就是建立目标程序与Aspect程序的连接(获得执行的对象、方法、参数等上下文信息),从而达到AOP的目的。这个本质上,还是使用的spring aop的动态代理。

    相关文章

      网友评论

          本文标题:spring aop和AspectJ的区别

          本文链接:https://www.haomeiwen.com/subject/qbnductx.html