SpringAop

AOP(面向切面编程)

切入点:匹配连接点的式子,能代表一个或者多个方法

连接点:程序中执行仍一位置,理解为方法的执行

通知:在切入点执行的操作,是共性功能

通知类:定义通知类

切面:描述通知与切入点的对应关系

入门案例

注解关系:

@EnableAspectJAutoProxy(aop注解代理自动配置)-->@Aspect(作为aop的类)-->@Pointcut()@Before
@Aspect//
public class MyAdvice {
//    定义切入点,excution执行的意思,void是update方法的返回值uodata()里面无参不需要加..,反之需要加
    @Pointcut("execution(void com.example.dao.BookDao.update())")
    public void pt(){

    }
//        定义通知
    @Before("pt()") //切面
    public void method(){
        System.out.println(System.currentTimeMillis());
    }
}

AOP工作流程

1,Spring容器启动

2,读取所有配置的切入点

3,初始化bean判断类中的方法是否匹配到切入点

匹配失败,创建对象

匹配成功,创建原始对象(目标对象)的代理对象

4,获取bean执行方法

获取bean,调用方法执行,完成

获取的bean是代理对象,就根据代理的运行模式运行原始方法活着增强的内容,完成操作

***创建的对象虽然一样,但是匹配成功后的是代理运行的,通过BookDao的getClass可以发现

 AOP切入点表达式

SpringAop_第1张图片

切入点表达式:

SpringAop_第2张图片

SpringAop_第3张图片

 AOP通知类型

前置通知:**

后置通知:**

异常通知:**

环绕通知:(重点)

//        定义通知
    @Around("pt()") //环绕通知Proceedingjoinpoint 继承了 JoinPoint。是在JoinPoint的基础上暴露出 proceed 这个方法。proceed很重要,这个是aop代理链执行的方法。
    public Object method(ProceedingJoinPoint pjt) throws Throwable {
        System.out.println("Before>>>>");
        Object proceed = pjt.proceed();//需要暴露接入点的方法,否则不会执行
        System.out.println("After>>>>");
        return proceed;
    }

案例:业务接口执行效率

//加到spring容器中
@Component
@Aspect
public class projectAdvice {
//    设置切入点

    @Pointcut("execution(* com.example.sevice.*Service.*(..))")
    public void pt(){
    };

//    设置切面
    @Around("projectAdvice.pt()")
    public Object timeLength(ProceedingJoinPoint pjt) throws Throwable {
        long l = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            pjt.proceed();
        }
        long l1 = System.currentTimeMillis();
        long length = l1-l;
        System.out.println(pjt.getSignature()); //获得签名
        System.out.println(pjt.getSignature().getDeclaringTypeName());
        System.out.println("业务的运行10000次的时间是:"+length);
        return 100;
    }


}

AOP获取数据:

SpringAop_第4张图片

 案例:百度网盘密码数据兼容处理(多数给出的密码会多出一个空格)

实现业务:

@Repository
public class UserDaoImpl implements UserDao {
    @Override
    public boolean equals(String url, String code) {
        return code.equals("root");
    }
}

 aop操作:

@Component
@Aspect
public class dataAspectj {
//    设置切点

    @Pointcut("execution(boolean com.wlb.service.UserService.equalscode(..))")
    public void po(){
    };

//    设置切面

    @Around("dataAspectj.po()")
    public Object aspect1(ProceedingJoinPoint pjt) throws Throwable {
//        获取传入的参数
        Object[] args = pjt.getArgs();
//        遍历参数
        for (int i = 0; i < args.length; i++) {
            if(args[i].getClass().equals(String.class)){ //如果是字符串
                args[i] = args[i].toString().trim();
            }
        }
//        返回方法重置
        return pjt.proceed(args);
    }
}

总结:SpringAop_第5张图片

案例:步骤

@EnableTransactionManagement //开启事务注解
    /**
     * import org.springframework.jdbc.datasource.DataSourceTransactionManager
* *调用jdbc的事务管理 * @param dataSource * @return */ @Bean public PlatformTransactionManager platformTransactionManager(DataSource dataSource){ DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(); dataSourceTransactionManager.setDataSource(dataSource); return dataSourceTransactionManager; }
//开启默认注解
@Transactional

事务属性:

timeout readonly等

属性:重点rollbackFor

error系列,运行时异常才会回滚,其他都不回滚

rollbackFor(**.class) 意思是遇到括号中的情况会回滚

举例:这种类型不会回滚,需要

@Transactional(rollbackFor ={Exception.class} )
@Override
    public void money(String out, String in, int money) throws Exception {
        accountDao.addMoney(in,money);
        if(true){
            throw new Exception("运行错误");
        }
        accountDao.reduceMoney(out,money);
    }

SpringAop_第6张图片

案例:追加日志。(无论转账是否成功,都要记录日志)

SpringAop_第7张图片

1,这种情况不会记录日志,因为三个协调员事务都合并到管理员的事务中去了,要么都执行,要么都不执行。

SpringAop_第8张图片

 2,这种情况会记录日志

 @Transactional(propagation = Propagation.REQUIRES_NEW)
    void log(String out,String in,int money);

使得,这个额外的日志事务不参与其他三个日志,无论他们是否异常,日志事务都会运行。

你可能感兴趣的:(java,spring)