ssm aop
Posted gg128
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ssm aop相关的知识,希望对你有一定的参考价值。
1.基于半配置半注解的AOP(依赖在最底下)
配置
<!--扫描的包--> <context:component-scan base-package="cn.test.service"/> <!--开启aop注解,proxy-target-class属性设置为true表示强制使用CGLIB代理--> <aop:aspectj-autoproxy/>
被切入方法
@Service("aop") public class AOPTest { public int add(int a,int b){ return a+b; } public Object sub(int a,int b){//该实例是在环绕通知中使用,所有返回值是object类型,否则报异常 return a-b; } public int mul(int a,int b){ int i=10/0; return a-b; } }
切入点
@Order(2)//指定切面的优先级,值越小优先级越高. @Aspect @Service public class AOPInfo { /*重用切入表达式,@Pointcut注解方法的访问权限符(public,private等)控制着重用切入表达式的可见性, 声明为 public时,在不同的包下需要写包名,相同的包下不用写包名*/ @Pointcut("execution(* cn.test.service.*.add(..))") public void PointCut(){ System.out.println("PointCut--"); } //前置通知 //使用重用表达式,PointCut()是注解 @Pointcut的方法名, @Before("PointCut()") public void before(){ System.out.println("before--"); } //后置通知,没有返回值 @After("PointCut()") public void after(){ System.out.println("after--"); } //返回通知,有返回值 @AfterReturning(value = "PointCut()",returning ="result") public void afterReturning(JoinPoint joinPoint,Object result){ String name = joinPoint.getSignature().getName(); System.out.println("afterReturning--"+name+":"+result); } //异常通知 @AfterThrowing(value = "execution(* cn.test.service.*.mul(..))",throwing = "ex") public void afterThrowing(JoinPoint joinPoint, Exception ex){ String name = joinPoint.getSignature().getName();//获取方法名 System.out.println("afterThrowing--"+name+":"+ex); } //环绕通知,被拦截的方法的返回值类型需要是object类型,否则报错,其他通知没有这个特征 @Around(value = "execution(* cn.test.service.*.sub(..))") public void around(ProceedingJoinPoint joinPoint){ String name = joinPoint.getSignature().getName();//获取方法名 System.out.println(name+":before--");//前置通知 try { System.out.println(name+":after--");//后置通知 Object result = joinPoint.proceed();//获取返回值 System.out.println("afterReturning--"+name+":"+result);//返回通知 } catch (Throwable throwable) { System.out.println("afterThrowing--"+name+":"+throwable);//异常通知 } System.out.println("around--");//环绕通知 } }
备注:
ProceedingJoinPoint类的方法:
Getargs方法 获取目标方法的参数
Getsignature方法:返回切入表达式的相关信息
Getarget方法:换回切入表达式的对象
Getthis:返回aop框架为目标对象生成的代理对象
proceed():获取返回值
切入点表达式的语法
完整的语法:Execution (“modifiers-pattern ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)throw-pattern”)
说明:execution:匹配执方法的连接点
modifiers-pattern 权限修饰符 可省略
ret-type-pattern 返回值类型 支持通配
declaring-type-pattern指定方法所属的类 支持通配 可省略//例如:@Before("execution(* spring2..*(int, int))")
name-pattern方法名 支持通配
param-pattern ..代表两个任意的参数假如是*则是代表一个任意类型的参数
throw-pattern 声明抛出异常 支持通配 可省略
例如:@Before("execution(* spring2.*.*(int, int))")第一个*表示返回类型 第二个*表示类名 第三个表示方法
2.完全依赖配置的AOP
重新整理待续
3.完全基于注解的AOP
重新整理待续
3.4) 合并切入点表达式
切入点表达式可以通过操作符 &&, ||, ! 结合起来
4)指定切面的优先级
<bean id="atime" class="spring2.AtithmeticCalculatorimp"></bean> <aop:aspect ref="atime" order="2">
可以通过@Order 注解指定(在类上指定),值越小 优先级越高.
6)基于xml的声明切面
所有的 Spring AOP 配置都必须定义在 <aop:config> 元素内部,. 对于每个切面都要创建一个 <aop:aspect> 元素,切入点必须定义在 <aop:aspect> 元素下
<!—对每个方法都进行匹配扫描 --> <bean id="atime" class="spring2.AtithmeticCalculatorimp"></bean> <aop:config > <!-- ref指向bean的id ,指定切面的对象,也就是@aspect注解的对象--> <aop:aspect ref="atime" order="2" > <!--切面表达式--> <aop:pointcut expression="execution(* spring2.*.*(int, int))" id="pointcut"/> <!--前置使用在beforeMethod方法上--> <aop:before method="beforeMethod" pointcut-ref="pointcut"/> <!--后置使用在afterMethod方法上 pointcut切入点表达式--> <aop:after method="afterMethod" pointcut="execution(* spring2.*.*(int, int))"/> <aop:after-returning method="returningMethod" pointcut-ref="pointcut" returning="result"/> <aop:after method="afterthrow" pointcut-ref="pointcut"/> <aop:around method="aroundmethod" pointcut-ref="pointcut" /> </aop:aspect> </aop:config>
3.事务管理
1)事务管理的原理
1>无论使用 Spring 的哪种事务管理策略(编程式或声明式), 事务管理器都是必须的,使用hibernate是管理事物的是session(session.transaction),spring策略是通过platformtransactionmanager接口实现,其中有三个方法gettransaction 获事务的方法,commit提交事务的方法,rollback回滚事物的方法,这个是没有与任何事务资源捆绑在一起,可以适应于任何的事务策略,spring没有任何的事物支持,只是包装了底层事务
2 >Gettransaction方法根据transactiondefinition参数,返回一个transactionstatus对象表示一个事务,transactionstatus被关联在当前的线程上
3 >Transactiondefinition接口定义一个事务规则,必须指定事务的隔离,事务的传播,事务的超时,只读状态
2)事务管理的方式
编程式事务管理
通过上述的三个方法实现,较为麻烦
声明式事务管理
Aop实现:在目标方法执行之前,切入开始事务,在目标方法执行之后,切入结束事务
方式1:
在xml中配置事物管理
<!-- 配置事务管理器 使用datasource.DataSourceTransactionManager 该类实现了platformtransactionmananger接口--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!—配置platformtransactionmananger接口,针对采用数据库连接的特定实现 --> <property name="dataSource" ref="datasource"></property> </bean>
<!—配置事物的切入点,指定事务管理器 transaction-manager="transactionManager"当transaction-manager 的值为transactionManager 时这个属性可以省略,不是则需要添加--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!—只能匹配一个 tx:attributes 可以匹配多个tx:method --> <tx:attributes> <!-- 根据方法名指定事务的属性 --> <tx:method name="purchase" propagation="REQUIRES_NEW"/> <!—所有以get开头的方法 read-only 只读模式--> <tx:method name="get*" read-only="true"/> <!—所有以find开头的方法 --> <tx:method name="find*" read-only="true"/> <!—所有方法 --> <tx:method name="*"/> </tx:attributes> </tx:advice>
<!-- aop 配置在那些元素上 --> <aop:config> <aop:pointcut expression="execution(execution(* spring2.*.*(int, int))id="txPointCut"/> <!—与aop绑定在一起,当切入点切入时,txAdvice 定义的处理也被切入,advisor 是从spring1.x中保留的,作用是将advice和切入点绑定在一起,然后一起切入 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/> </aop:config>
说明:tx:advice包含事务的隔离,传播,超时属性,只读,对指定事务的回滚,对指定事务不回滚等
tx:method的属性如下
Name:必选属性 配置关联的方法名,支持通配符 例如get* handle* on*event等
Propagation:事务的传播(在已经有事务的前提下,调用另外一个事务的情形),该属性为Propagation的枚举值,默认值为PROPAGATION_REQUIRED支持当前事务(在事务中,就不新建事务),如果当前没有事务,就新建一个事务,PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
Isolation:隔离级别isolation枚举的值,默认值是ISOLATION_DEFAULT,ISOLATION_READ_UNCOMMITTED读未提交,ISOLATION_READ_COMMITTED读已提交,ISOLATION_REPEATABLE_READ可重复读,ISOLATION_SERIALIZABLE序列化
Timeout:指定事务的超时时间
Read-only 是否只读
Rollback-for 事务回滚的异常类,需要使用全类名,多个用逗号隔开
No-rollback-for:指定不触发事务回滚的异常类,其余同上
说明:在默认的情况下,只有在运行时异常和unchecked异常时,spring事务才会回滚,如果抛出checked异常时,则事务不会回滚,假如需要回滚需要设置rollback-for属性,如果希望抛出指定的异常不回滚,那么需要设置no-rollback-for
方式2
使用@transactional配置事务管理
在方法上指定@transactional,表示在这个方法上具有事务性
@transactional可指定的方法,属性值同上
需要在xml中配置
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="datasource"></property> </bean> <!-- 启动事务注解--> <tx:annotation-driven transaction-manager="transactionManager"/>
5.springide插件的安装springsource-tool-suite-3.9.6.RELEASE-e4.9.0-updatesite更加方便spring的书写
6. Spring 对 JDBC 的支持
1)JdbcTemplate
1> 配置JdbcTemplate
<context:property-placeholder location="classpath:jdbc.properties"/> <bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="${user}"></property> <property name="password" value="${password}"></property> <property name="jdbcUrl" value="${jdbcUrl}"></property> <property name="driverClass" value="${driverClass}"></property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="datasource"></property> </bean>
2> 使用JdbcTemplate查询数据库的方法
execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;
batchUpdate方法用于执行批处理相关语句;
query方法及queryforobject方法:用于执行查询相关语句;
queryforobject:单行查询
String sql2="select * from users where id=1";
//需要注入的bean
RowMapper<Users> rm=new BeanPropertyRowMapper<>(Users.class);
Users users = jdbcTemplate.queryForObject(sql2, rm);
query:多行查询 返回list集合
String sql3="select * from users where id>?";
RowMapper<Users> rm1 = new BeanPropertyRowMapper<>(Users.class);
List<Users> query = jdbcTemplate.query(sql3, rm1,0);
call方法:用于执行存储过程、函数相关语句。
备注:注意jdbcTemplate尽量只执行查询操作,莫要进行更新,否则很容易破坏Hibernate的二级缓存体系,但在一般与hibernate等使用时一般不会用到spring的JdbcTemplate,经典的 JDBC 用法中, SQL 参数是用占位符 ? 表示
2)NamedParameterJdbcTemplate
1> 具名参数只在 NamedParameterJdbcTemplate 中得到支持
2> 配置NamedParameterJdbcTemplate
<context:property-placeholder location="classpath:jdbc.properties"/> <bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="${user}"></property> <property name="password" value="${password}"></property> <property name="jdbcUrl" value="${jdbcUrl}"></property> <property name="driverClass" value="${driverClass}"></property> </bean> <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"><constructor-arg ref="datasource"></constructor-arg> </bean>
3)使用
NamedParameterJdbcTemplate namedParameterJdbcTemplate = ctx.getBean(NamedParameterJdbcTemplate.class);//获取对象 //使用别名:user,:password String sql="insert into users(user,pwd) values(:user,:password)"; Map<String ,Object> paramMap=new HashMap<>(); paramMap.put("user", "12qwe"); paramMap.put("pwd", "weq"); namedParameterJdbcTemplate.update(sql, paramMap);