#AOP(面象切面编程,是oop的扩展和衍生)
* aop:是横向抽取机制取代了传统的纵行继承
* aop:可以用于权限的校验,日志的监控deng。
#Spring的AOP底层实现原理
* jdk的动态代理(通过目标类实现了接口,使用jdk的动态代理)
*cglib的代理方式(目标类没有实现接口,使用cglib的代理)
#Spring的AOP开发
* AOP思想最早有AOP联盟组织提供
* Spring的AOP有自己的实现方式(比较繁琐),于是Spring借用 AspectJ作为自生的AOP的开发。
* Spring有两套AOP(一套是自己的AOP,另一套是AspectJ的AOP)
AspectJ的AOP使用较多。
#Spring中aop的术语
* Joinpoint:连接点,可以被拦截的点(可以被增强的点)
* Pointcut:切入点,实际被拦截的点
* Advice:通知,增强(方法层面的增强,在方法时加强,例如在登入方法之前,要实现权限校验的方法)
* Introduction:引介.(类层面的增强)
* target:被增强的对象()
* Weaving:织入
* Proxy:代理对象
* Aspect:切面,由多个通知和切入点组合
* [外链图片转存失败(img-C41jYx5S-1566801164230)(https://i.imgur.com/NLHC6Zh.png)]
#Aop开发的入门
* eg:在执行删除之前进行权限的校验
* 要增强的方法的申明(chechPri())
* public class StudentAspectXml {
public void chechPri() {
System.out.println("权限的校验");
}
}
* 将切面类交给Spring管理
*<bean id="studentAspect" class="com.echo.Proxy.StudentAspectXml"/>
* 切面的引入
<!--切面的引入-->
<aop:config>
<!--表示那个方法要增强-->
<aop:pointcut id="pointcut1" expression="execution(* com.echo.daoimpl.StudentDaoImpl.delete(..))"/>
<!--切面编程,指定要插入的方法-->
<aop:aspect ref="studentAspect">
<!--check方法时在save()方法之前执行-->
<aop:before method="chechPri" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
#AOP通知的类型
* 前置 <aop:before />(可以获得切入点的信息JoinPoint)
*
<aop:before method=“chechPri” pointcut-ref=“pointcut1”/>
*对应的增强方法: public void chechPri(JoinPoint joinPoint) {
System.out.println("权限的校验" + joinPoint);
}
*后置<aop:after-returning/>
* <aop:after-returning method=" writelog" pointcut-ref="pointcut2" returning="result"/>
*
* public void writelog(Object result) { //returning的结果值要和 方法的参数名 同
System.out.println("这时删除后的通知");
}
*环绕<aop:around/>在之前和之后都会执行
* <aop:around method="around" pointcut-ref="pointcut3"/>
*
*异常 <aop:after-throwing> throwing中的指对应加强方法的参数ex
* <aop:after-throwing method="afterThrow" pointcut-ref="pointcut4" throwing="ex"/>
*
*最终通知 <aop:after/>
* <aop:after method=" after" pointcut-ref="pointcut4"/>-->
#spring的切入点表达式的写法
* 基于executin的函数完成的
* 语法
* 访问修饰符 返回类型 包名.类名.方法名(参数名)
* eg:public void com.echo.Dao.StudentDao.save(…)
* public 可以不写 ,* 可以代表任意的返回类型,参数名用…表示
* execution(* com.echo.daoimpl.StudentDaoImpl.add(…))
* com.echo.daoimpl.StudentDaoImpl+.add(…) //+代表当前和其子类中的add(…)
![](https://i.imgur.com/dfmwD1O.png)
#Spring的注解AOP开发
* 切入点的注解(将切入点注解放在一个方法上,在调用具体的增强方法时用类.方法名引入 切入点value = “StudentAspect.Pointcout1()”)
*//环绕增强
@Around(value = "StudentAspect.Pointcout1()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕加强前");
Object object = joinPoint.proceed();//执行upadate()方法
System.out.println("环绕加强后");
return object;
}
* // 切入点注解:
@Pointcut(value ="execution(* com.echo.daoImpl.StudentDaoImpl.update(..))")
public void Pointcout1(){}
#jdbc模板保存数据
* @Test
public void jdbcTemplate() {
//连接池
DriverManagerDataSource dataSource = new DriverManagerDataSource();
//加载驱动
dataSource.setDriverClassName(“com.mysql.jdbc.Driver”);
dataSource.setUrl(“jdbc:mysql:///mybatis”);
dataSource.setUsername(“root”);
dataSource.setPassword(“123456”);
//创建jdbc模板
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String sql = “insert into course values(?,?,?,?)”;
jdbcTemplate.update(sql, “C007”, “java”, “c002”, 90);
}
* 将连接池和模板交给Spring管理
* <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<!--jdbc的模板-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
* 测试方法
* @Resource(name = "jdbcTemplate")
private JdbcTemplate jdbcTemplate;
@Test
public void test() {
//String sql = "insert into course values(?,?,?,?)";
String sql = "delete from course where Cno=?";
jdbcTemplate.update(sql, "C009");
}
#dbcp连接池(BasicDataSource)
*
*抽取配置到属性文件
*jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///mybatis
jdbc.username=root
jdbc.password=123456
*在spring的配置文件中配置
*
<context:property-placeholder location=“classpath:jdbc.properties”/>
* 引入属性文件的值
*
#事务管理
* 什么时事务:逻辑上的一组操作,组成这个操作的单元,要么都成功,要么都失败
*事务的特性
* 原子性:事务不可分给
* 一致性:事务执行前后的数据保持一致
* 隔离性:一个事务的执行不应该受到其它事务的干扰
* 持久性:一旦事务结束,数据就持久化到数据库
* 如果不考虑隔离性引发安全性问题
*读问题
*脏读:一个事务读到另一个事务未提交的数据
*不可重复读:一个事务读到另一个事务已经提交的update
的数据,导致一个事务中多次查询结果不一致
*虚读、幻读:一个事务读到另一个事务已经提交的insert的数据,导致一个事务中多次查询结果不一致。
*写问题
*丢失更新
* 解决读问题
*设置事务的隔离级别
*Read uncommitted:未提交读,任何读问题解决不了。
*Read committed :已提交读,解决脏读,但是不可重复读和虚读有可 能发生。
*Repeatable read:重复读,解决脏读和不可重复读,但是虚读有可能发生。
*Serializable:解决所有读问题。
#spring的事务管理的
# 声明式事务管理
* 声明事务管理器(要引入数据源datasource)
* 配置事务的通知,增强(对transfer()进行增强)
<tx:advice id=“txadvice” transaction-manager=“transaction”>
<tx:attributes>
<tx:method name="transfer" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
*引入aop事务
<!--aop的配置-->
<aop:config>
<aop:pointcut id="poincut1" expression="execution(* com.echo.serviceImpl.AccountServiceImpl.transfer(..))"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="poincut1"/>
</aop:config>
#注解式的事务管理
* 声明事务管理器(引入数据源datasource)
<bean id="transaction" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
* 开启事务管理的注解开发
<!--事务管理的注解-->
<tx:annotation-driven transaction-manager="transaction"/>
* 在要使用事务管理的类上加上注解
*@Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)