欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 宝鼎售后问题提交 | 后台管理


新闻资讯

MENU

软件开发知识

默认pointcutBeanName为aop:pointcut标签中定义的id属性 昆山软件定制开发 : 如果aop:p

点击: 次  来源:宝鼎软件 时间:2017-06-01

原文出处: 五月的仓颉

媒介

前面写了六篇文章具体地阐明白Spring Bean加载流程,这部门完了之后就要进入一个较量坚苦的部门了,就是AOP的实现道理阐明。为了探究AOP实现道理,首先界说几个类,一个Dao接口:

public interface Dao {
    public void select();
    public void insert();
}

Dao接口的实现类DaoImpl:

public class DaoImpl implements Dao {

    @Override
    public void select() {
        System.out.println("Enter DaoImpl.select()");
    }

    @Override
    public void insert() {
        System.out.println("Enter DaoImpl.insert()");
    }

}

界说一个TimeHandler,用于要领挪用前后打印时间,在AOP中,这饰演的是横切存眷点的脚色:

public class TimeHandler {

    public void printTime() {
        System.out.println("CurrentTime:" + System.currentTimeMillis());
    }

}

界说一个XML文件aop.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd


http://www.springframework.org/schema/aop


http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <bean id="daoImpl" class="org.xrq.action.aop.DaoImpl" />
    <bean id="timeHandler" class="org.xrq.action.aop.TimeHandler" />

    <aop:config proxy-target-class="true">
        <aop:aspect id="time" ref="timeHandler">
            <aop:pointcut id="addAllMethod" expression="execution(* org.xrq.action.aop.Dao.*(..))" />
            <aop:before method="printTime" pointcut-ref="addAllMethod" />
            <aop:after method="printTime" pointcut-ref="addAllMethod" />
        </aop:aspect>
    </aop:config>

</beans>

写一段测试代码TestAop.java:

public class TestAop {

    @Test
    public void testAop() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring/aop.xml");

        Dao dao = (Dao)ac.getBean("daoImpl");
        dao.select();
    }

}

代码运行功效就不看了,有了以上的内容,我们就可以按照这些跟一下代码,看看Spring到底是如何实现AOP的。

AOP实现道理——找到Spring处理惩罚AOP的源头

有许多伴侣不肯意去看AOP源码的一个很大原因是因为找不到AOP源码实现的进口在那边,这个确实是。不外我们可以看一下上面的测试代码,就普通Bean也好、AOP也好,最终都是通过getBean要领获取到Bean并挪用要领的,getBean之后的工具已经前后都打印了TimeHandler类printTime()要领内里的内容,可以想见它们已经是被Spring容器处理惩罚过了。

既然如此,那无非就两个处所处理惩罚:

  1. 加载Bean界说的时候应该有过非凡的处理惩罚
  2. getBean的时候应该有过非凡的处理惩罚

因此,本文环绕【1.加载Bean界说的时候应该有过非凡的处理惩罚】展开,先找一下到底是那边Spring对AOP做了非凡的处理惩罚。代码直接定位到DefaultBeanDefinitionDocumentReader的parseBeanDefinitions要领:

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    if (delegate.isDefaultNamespace(root)) {
        NodeList nl = root.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                if (delegate.isDefaultNamespace(ele)) {
                    parseDefaultElement(ele, delegate);
                }
                else {
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        delegate.parseCustomElement(root);
    }
}

正常来说,碰着<bean id=”daoImpl”…>、<bean id=”timeHandler”…>这两个标签的时候,城市执行第9行的代码,因为<bean>标签是默认的Namespace。可是在碰着后头的<aop:config>标签的时候就纷歧样了,<aop:config>并不是默认的Namespace,因此会执行第12行的代码,看一下:

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
    String namespaceUri = getNamespaceURI(ele);
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if (handler == null) {
        error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
        return null;
    }
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

因为之前把整个XML理会为了org.w3c.dom.Document,org.w3c.dom.Document以树的形式暗示整个XML,详细到每一个节点就是一个Node。