关于aop实现的几点感想,在网上查资源总结的一点小心得

关于aop使用java代码实现的流程:

    1.准备java测试类PersonAOP(主要在两个run方法指定位置采用aop思想加上指定代码):

    

import org.springframework.aop.Advisor;

/**
 *纯java实现AOP功能范例
 */
public class PersonAOP {
    public void run(){
        System.out.println("这是第一个run方法");
    }

    public void run(int i){
        System.out.println("这是第二个run"+i+"方法");
    }

    public void print(){
        System.out.println("这是一个打印方法");
    }

    //是否启用代理模式
    public void proxy(Advisor advisor){

    }
}

  2.为方便扩展,添加指定代码的方法抽象出个父类AOPPoint

    

import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;

/**
 * 切入点规则父类
 */
public abstract class AOPPoint {
    //切入点
    public JdkRegexpMethodPointcut point(String regularExpression) {
        JdkRegexpMethodPointcut cut = new JdkRegexpMethodPointcut();
        //cut.setPattern("指定明确方法的位置");
        cut.setPattern(regularExpression);//或者指定匹配关系的正则表达式
        return cut;
    }

    //通知
    //如果在方法提之前需要加入一些操作
    public abstract Advice before();

    //如果在方法提之后执行
    public abstract Advice after();

    //如果方法体被包含
    public abstract Advice around();

    /**
     *
     * @param regularExpression 可以时匹配的正则表达式,也可以是明确的方法的路径
     * @param location
     * @return
     */
    public abstract Advisor rule(String regularExpression,String location);
}

3.实现类AOPTest

    

import AOP.AOPPoint;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Advisor;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;

import java.lang.reflect.Method;

public class AOPTest extends AOPPoint {


    @Override
    public Advice before() {
        Advice before = new MethodBeforeAdvice() {
            @Override
            public void before(Method method, Object[] args, Object obj)
                    throws Throwable {
                System.out.println("before...拦截");
            }
        };
        return before;
    }

    @Override
    public Advice after() {
        Advice after = new AfterReturningAdvice() {

            @Override
            public void afterReturning(Object returnValue, Method method,
                                       Object[] args, Object target) throws Throwable {
                System.out.println("afterReturning...拦截");
            }
        };
        return after;
    }

    @Override
    public Advice around() {
        Advice advice = new MethodInterceptor() {
            //哈哈,看到这个是不是和动态代理中的那个方法很像
            @Override
            public Object invoke(MethodInvocation methodInv) throws Throwable {
                System.out.println("前面拦拦...");
                Object resObj = methodInv.proceed();//放行
                System.out.println("后面拦拦...");
                return resObj;
            }
        };
        return advice;
    }

    @Override
    public Advisor rule(String regularExpression, String location) {
        JdkRegexpMethodPointcut cut = super.point(regularExpression);
        String judge = location.trim();
        Advice advice = null;
        switch (judge) {
            case "before":
                advice = this.before();
                break;
            case "after":
                advice = this.after();
                break;
            case "around":
                advice = this.around();
                break;
        }
        //切面 = 切点 + 通知
        Advisor advisor = new DefaultPointcutAdvisor(cut, advice);
        return advisor;
    }
}

4.组装工厂AOPFactory

    

import org.springframework.aop.Advisor;
import org.springframework.aop.framework.ProxyFactory;

public class AOPFactory {
    /**
     * 组装工厂, 说白了就是代理模式的升级版
     * @param aa 原型对象,也就是要被切面使用的类
     * @param advisor
     * @return
     */
    public static Object proxy(Object aa, Advisor advisor){
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(aa);//给代理工厂一个原型对象
        proxyFactory.addAdvisor(advisor);//给代理工厂一个切面
        Object ob = proxyFactory.getProxy();//从代理工厂中获取一个代理后的对象
        return ob;
    }
}
    <!--配置事务管理,如果想更加精细控制,则使用注解事务 -->
    <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 配置通知(配置事务执行的方法定义的名称规则) -->
    <tx:advice id="myAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="del*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="*" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <!-- 配置AOP的规则 -->
    <aop:config>
        <!-- 配置切入点 -->
        <aop:pointcut id="pc" expression="execution(* com.zc.service..*Service*.*(..))"/>
        <aop:advisor pointcut-ref="pc" advice-ref="myAdvice"/>
    </aop:config>

    <aop:config proxy-target-class="true"></aop:config>

5测试类JavaAOP

    

import AOP.impl.AOPTest;
import com.zc.dto.PersonAOP;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.Invocation;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.Test;
import org.springframework.aop.Advisor;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;

import java.lang.reflect.Method;

/**
 * 纯Java的方式实现切面(拦截)技术
 */
public class JavaAOP {
    //和动态代理类似
    @Test
    public void demo(){

        //获取切面规则,主要是面向切面的方法,以及切入点的位置(这里有before,after,around三种)
        AOPPoint  aop = new AOPTest();
        Advisor advisor = aop.rule(".*.print.*","before");

        //获取代理后的对象
        PersonAOP p2 = (PersonAOP) AOPFactory.proxy(new PersonAOP(),advisor);

        p2.run();
        p2.print();//不会拦
        p2.run(3333);


    }
}

以上是java代码实现的基本步骤,说白了就是要注意:1切入面(方法),2切入点(移植代码的位置) 

了解原理之后在看spring 利用aop完成事务提交和回滚就特别好理解了,直接上代码

xml里面的配置

        

<!--配置事务管理,如果想更加精细控制,则使用注解事务 -->
    <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 配置通知(配置事务执行的方法定义的名称规则) -->
    <tx:advice id="myAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="del*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="*" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <!-- 配置AOP的规则 -->
    <aop:config>
        <!-- 配置切入点 -->
        <!--针对execution(* com.zc.Service..*Service*.*(..))的说明,
            * com.zc.service..*Service*.*(..)
            * 指的是返回的类型是任意的
            com.zc.service 指切面路径
            .. 有两种 .表示当前包下面的类  .. 表示当前包及其子包下的所有类
            *Service* 类名的规则,中间必须有Service,前后随意
            * 表示方法名随意,可指定
            (..)参数为任意参
          -->
        <aop:pointcut id="pc" expression="execution(* com.zc.service..*Service*.*(..))"/>
        <aop:advisor pointcut-ref="pc" advice-ref="myAdvice"/>
    </aop:config>

    <aop:config proxy-target-class="true"></aop:config>

    

其中给自己挖了个坑,没配aop事务之前在 在用公司给的框架里有这个配置

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor"/>

结果导致一直报异常

org.springframework.beans.factory.NoSuchBeanDefinitionException

后来发现是生成bean和需求产生的bean(加上这个配置后,显示的是个代理bean) 两边不匹配出错,查了下这个

DefaultAdvisorAutoProxyCreator

貌似很强大,待以后研究

参考文章:https://blog.csdn.net/qq_26525215/article/details/52400791


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值