SpringAOP
spring AOP概念
-
AOP的概念
-
AOP:面相切面编程思想,即将一些共性的内容进行抽取,在需要用到的地方,以动态代理的方式进行插入在不修改源码的基础上,还能对源码进行前后的增强
-
底层实现技术:动态代理
-
AOP的应用: 权限拦截、日志的输出、性能的检测、事务管理
-
-
AOP术语
- 切面(Aspect):横切关注点被模块化的特殊对象(切点+通知/增强=切面)
- 通知/增强(advice):切面必须要完成的工作,增强的那段代码方法
- 目标(Target):被通知的对象
- 代理(Proxy):向目标对象应用通知之后创建的对象
- 连接点(Joinpoint):程序执行的某个特定位置,即可以被增强的方法
- 切点(pointcut):每个类都拥有多个连接点,即要被增强的方法,小于等于连接点个数
- 织入: 切入点集成到切面的这一个过程,就叫做织入过程
Spring AOP的环境搭建
-
导入jar包
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-aop-4.2.4.RELEASE.jar
spring-aspects-4.2.4.RELEASE.jar -
在配置文件中加入aop的命名空间
<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:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
-
配置文件中的配置
<!-- 配置扫描器,扫描com.edu以及其子包下的注解 --> <context:component-scan base-package="com.edu"/> <!-- 使AspectJ注解生效,自动为匹配的类生成代理对象 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
-
创建切面类,增强方法
@Order(1) //注解指定切面的优先级 @Aspect //声明此类是一个切面类 @Component("userAspect") //放入spring容器 public class userAspect { //声明切入点表达式,可以避免代码重入,即下面的通知可@Before("pointCut()")书写 @Pointcut("execution(* com.edu.user.User.*(..))") public void pointCut() { } //声明该方法是一个前置通知:在目标方法开始之前执行 @Before("execution(* com.edu.user.User.*(..))") //@Before("pointCut()") //也可以调用上面的切入点 public void before() { System.out.println("执行方法之前!!!"); } }
通知类型
通知类型:
-
@Before:前置通知 在连接点之前增强 权限拦截
-
@After:后置通知 在连接点之后增强(无论是否出现异常) 日志输出
-
@Around:环绕通知 在连接点之前和连接点之后都增强 性能检测
/** * 环绕通知需要携带ProceedingJoinPoint类型的参数 * 环绕通知类似于动态代理的全过程,ProceedingJoinPoint类型的参数可以决定是否执行目标方法,即proceed()方法 * 且环绕通知必须有返回值,返回值即为目标方法的返回值 * @param joinPoint * @return */ @Around(value = "execution(* com.edu.user.User.*(..))") public Object around(ProceedingJoinPoint joinPoint) { Object result = null; String method = joinPoint.getSignature().getName(); try { //前置通知 System.out.println(method + "被执行了!!!"); //执行原方法 result = joinPoint.proceed(); //返回通知 System.out.println(method + "执行了!!!"); } catch (Throwable e) { //异常通知 System.out.println(method + "出现异常了!!!"); throw new RuntimeException(e); } //后置通知 System.out.println(method + "执行完了!!!"); return result; }
-
@AfterRunning:返回通知, 在方法返回结果之后执行,可以访问到方法的返回值
/** * 返回通知, 在方法返回结果之后执行,可以访问到方法的返回值 * @param joinPoint * @param result //方法的返回值 */ @AfterReturning(value = "execution(* com.edu.user.User.*(..))", returning = "result") public void afterReturning(JoinPoint joinPoint,Object result) { //获取切点的方法名 String method = joinPoint.getSignature().getName(); System.out.println(method+"方法被执行完了!!!"); }
-
@AfterThrowing:异常通知, 在方法抛出异常之后,可以访问到方法抛出的异常
/** * 在目标方法出现异常时会执行的代码 * 可以访问到异常对象,且可以指定在出现特定的异常时(NullPointExecption)执行此代码 * @param joinPoint * @param e */ @AfterThrowing(value = "execution(* com.edu.user.User.*(..))",throwing = "e") public void afterThowing(JoinPoint joinPoint,Exception e) { String method = joinPoint.getSignature().getName(); System.out.println(method + "方法出现了"+ e + "异常"); }
JdbcTemplate
-
概念
jdbcTemplate是spring提供的dao层用来和数据库数据交互的技术
-
JdbcTemplate的使用方式
-
导包:spring-jdbc.jar、spring-tx.jar
-
在applicationContext.xml文档中配置
<!-- 加载外部配置文件,jdbc.properties --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- c3p0连接池提供给JdbcTemplate一个数据库连接 --> <bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.userName}"></property> <property name="password" value="${jdbc.passWord}"></property> </bean> <!-- jdbcTemplate --> <bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="c3p0"></property> </bean>
- 使用JdbcTemplate实现增删改查
public class UserDaoImp implements UserDao { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } //增删改与QueryRunner类似 public void save() { String sql = "insert into user values(?,?)"; jdbcTemplate.update(sql, "zhangshan",20); } //全查使用BeanPropertyRowMapper() public void findAll() { String sql = "select * from user"; List<User> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class)); for (User user : list) { System.out.println(user); } } //查询单个 public void findByUserName() { String sql = "select * from user where username = ?"; User user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class),"李四"); System.out.println(user); } //聚合查 public void findCount() { String sql = "select count(*) from user"; Long count = jdbcTemplate.queryForObject(sql, long.class); System.out.println(count); } }
-
JdbcTemplate 在dao层的两种注入方式
- set方式注入,能够使用注解
- 基继承方式让jdbctemplate继承JdbcDaoSupport 不能使用注解,applicationContext.xml需要用set方式配置,继承的父类中有jdbctemplate,可以使用getJdbcTemplate()获取父类的jdbctemplate对象
spring 事务的全xml配置方式
<!-- 加载外部配置文件,jdbc.properties -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- c3p0连接池提供给JdbcTemplate -->
<bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.userName}"></property>
<property name="password" value="${jdbc.passWord}"></property>
<!-- 注入事务管理器对象 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="c3p0"></property>
</bean>
<!-- 配置事务管理器对哪些方法开启事务 -->
<tx:advice transaction-manager="transactionManager" id="transacTion">
<tx:attributes>
<tx:method name="transfer" />
</tx:attributes>
</tx:advice>
<!-- 切点 -->
<aop:config>
<aop:pointcut expression="execution(* com.edu.serviceImp.TransferServiceImp.transfer(..))" id="transfer"/>
<!-- 针对事务的配置标签 -->
<aop:advisor advice-ref="transacTion" pointcut-ref="transfer"/>
</aop:config>
spring 事务注解加xml配置方式
<!-- 加载外部配置文件,jdbc.properties -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- c3p0连接池提供给JdbcTemplate -->
<bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.userName}"></property>
<property name="password" value="${jdbc.passWord}"></property>
</bean>
<!-- 注入事务管理器对象 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="c3p0"></property>
</bean>
<!-- 开启声明式事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 自己的类,直接开启注解扫描器 -->
<context:component-scan base-package="com.edu"/>
使用方式:在需要开启事务的方法或者类上加上注解@Transactional