zoukankan      html  css  js  c++  java
  • Spring AOP 方式一 ProxyFactoryBean

    先看例子

    <bean id="personTarget" class="com.mycompany.PersonImpl">
        <property name="name" value="Tony"/>
        <property name="age" value="51"/>
    </bean>
    
    <bean id="myAdvisor" class="com.mycompany.MyAdvisor">
        <property name="someProperty" value="Custom string property value"/>
    </bean>
    
    <bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor">
    </bean>
    
    <bean id="person"
        class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="proxyInterfaces" value="com.mycompany.Person"/>
    
        <property name="target" ref="personTarget"/>
        <property name="interceptorNames">
            <list>
                <value>myAdvisor</value>
                <value>debugInterceptor</value>
            </list>
        </property>
    </bean>

    配置点:

    1、interceptorNames    拦截器数组

    2、targetName   目标类

    3、singleton   是否单例,默认true

    4、proxyInterfaces  代理接口

    5、optimize   建议使用cglib

    6、proxyTargetClass 

    问题:

    1、如何判断是使用jdk代理还是使用CGLIB?

      答:默认使用jdk,如果没有使用接口或optimize 为true或proxyTargetClass 为true

    2、为什么interceptorNames可以是什么类型?

         答:可以是Advisor 或 MethodInterceptor 或MethodBeforeAdvice 或 AfterReturningAdvice 或 ThrowsAdvice 的实现类,Spring会自动把以上类封装成Advisor

    实现原理:

    ProxyFactoryBean是FactoryBean的实现类,其接口getObject会返回一个代理对象;如果代理方式为JDK,那么获取对象将返回一个JDK的代理对象,执行方式时将执行继承InvocationHandler的invoke方法

    JdkDynamicAopProxy.invoke方法流程如下

    1、如果方法是equals或hashCode 会特殊处理,暂不将

    2、如果方式是继承自Advice,将直接执行

    3、然后以递归的方式执行各个拦截器

    MethodBeforeAdviceInterceptor 执行如下
    
    public Object invoke(MethodInvocation mi) throws Throwable {
            this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
            return mi.proceed();
        }
    AfterReturningAdviceInterceptor 执行如下
    
    public Object invoke(MethodInvocation mi) throws Throwable {
            Object retVal = mi.proceed();
            this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
            return retVal;
        }
    ThrowsAdviceInterceptor 执行如下
    
    public Object invoke(MethodInvocation mi) throws Throwable {
            try {
                return mi.proceed();
            }
            catch (Throwable ex) {
                Method handlerMethod = getExceptionHandler(ex);
                if (handlerMethod != null) {
                    invokeHandlerMethod(mi, ex, handlerMethod);
                }
                throw ex;
            }
        }
    /**
         * Determine the exception handle method. Can return null if not found.
         * @param exception the exception thrown
         * @return a handler for the given exception type
         */
        private Method getExceptionHandler(Throwable exception) {
            Class exceptionClass = exception.getClass();
            if (logger.isTraceEnabled()) {
                logger.trace("Trying to find handler for exception of type [" + exceptionClass.getName() + "]");
            }
            Method handler = this.exceptionHandlerMap.get(exceptionClass);
            while (handler == null && !exceptionClass.equals(Throwable.class)) {
                exceptionClass = exceptionClass.getSuperclass();
                handler = this.exceptionHandlerMap.get(exceptionClass);
            }
            if (handler != null && logger.isDebugEnabled()) {
                logger.debug("Found handler for exception of type [" + exceptionClass.getName() + "]: " + handler);
            }
            return handler;
        }
    private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable {
            Object[] handlerArgs;
            if (method.getParameterTypes().length == 1) {
                handlerArgs = new Object[] { ex };
            }
            else {
                handlerArgs = new Object[] {mi.getMethod(), mi.getArguments(), mi.getThis(), ex};
            }
            try {
                method.invoke(this.throwsAdvice, handlerArgs);
            }
            catch (InvocationTargetException targetEx) {
                throw targetEx.getTargetException();
            }
        }
  • 相关阅读:
    中文词频统计
    复合数据类型,英文词频统计
    Mybatis 异常:Cause: java.io.IOException: Could not find resource com.xxx.xxx.xml
    Ajax:修改了项目的ajax相关代码,点击运行没有效果
    大数据应用期末总评
    分布式并行计算MapReduce
    分布式文件系统HDFS 练习
    安装关系型数据库MySQL和大数据处理框架Hadoop
    爬虫综合大作业
    爬取全部的校园新闻
  • 原文地址:https://www.cnblogs.com/benx/p/3414779.html
Copyright © 2011-2022 走看看