spring系列(五):切面编程(aop)3
2017-12-23 10:44
507 查看
开发环境:jdk1.7 spring3.2.2
前两篇文章讲了各种增强处理,这篇文章再接着讲用注解定义增强以及切面编程的具体应用
一 用注解定义增强处理
除了实现Spring提供的特定接口,Spring还通过集成AspectJ实现了以注解的方式定义增强类,
大大减少了配置文件中的工作量。
增强处理代码
package com.obtk.advise;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import com.obtk.entitys.UserEntity;
@Aspect
public class AnnotationAdvise {
private static final Logger log = Logger.getLogger(AnnotationAdvise.class);
/*
@Before("execution(* com.obtk.dao.*.saveUser(..))")
public void beforMeth(JoinPoint jp) {
log.info("注解定义的前置增强==,调用者:"+jp.getTarget()
+",方法名:"+jp.getSignature().getName()
+",参数列表:"+Arrays.toString(jp.getArgs()));
}
@AfterReturning(pointcut="execution(* com.obtk.dao.*.saveUser(..))",returning="returnValue")
public void afterMeth(JoinPoint jp,Object returnValue){
log.info("注解定义的后置增强==,调用者:"+jp.getTarget()
+",方法名:"+jp.getSignature().getName()
+",参数列表:"+Arrays.toString(jp.getArgs())
+",返回值:"+returnValue);
}
@AfterThrowing(pointcut="execution(* com.obtk.dao.*.saveUser(..))",throwing="e")
public void afterPaoChu(JoinPoint jp,RuntimeException e){
log.info("注解定义的异常抛出增强==,调用者:"+jp.getTarget()
+",方法名:"+jp.getSignature().getName()
+",参数列表:"+Arrays.toString(jp.getArgs())
+",异常信息===>:"+e);
}
*/
//注解定义环绕增强
@Around("execution(* com.obtk.dao.*.saveUser(..))")
public Object arundAdvise(ProceedingJoinPoint jp){
log.info("注解定义的前置增强==,调用者:"+jp.getTarget()
+",方法名:"+jp.getSignature().getName()
+",参数列表:"+Arrays.toString(jp.getArgs()));
Object result=null;
try {
result=jp.proceed();
log.info("注解定义的后置增强==,调用者:"+jp.getTarget()
+",方法名:"+jp.getSignature().getName()
+",参数列表:"+Arrays.toString(jp.getArgs())
+",返回值:"+result);
} catch (Throwable e) {
log.info("注解定义的异常抛出增强==,调用者:"+jp.getTarget()
+",方法名:"+jp.getSignature().getName()
+",参数列表:"+Arrays.toString(jp.getArgs())
+",异常信息===>:"+e);
}
return result;
}
}
切入点代码
package com.obtk.dao;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import com.obtk.entitys.UserEntity;
import com.obtk.utils.MybatisUtil;
public class UserDaoImpl implements IUserDao{
public int saveUser(UserEntity theUser) {
System.out.println("方法执行前....");
int result=0;
SqlSession session=null;
try {
//4.得到session
session=MybatisUtil.getSession();
//5.执行语句
result=session.insert("user.saveOne", theUser);
session.commit();
//添加完成可以取出启动增长的主键
System.out.println("添加成功!");
} catch (Exception e) {
System.out.println("抛出了异常");
session.rollback();
throw new RuntimeException("发生了异常");
}finally{
MybatisUtil.closeSession();
}
return result;
}
}
配置
<?xml version="1.0" encoding="UTF-8"?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="userDao" class="com.obtk.dao.UserDaoImpl"></bean>
<!-- 增强处理的代码 -->
<bean id="aspectBean" class="com.obtk.advise.AnnotationAdvise"></bean>
<!-- 启动增强处理注解的支持 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
二 aop具体应用
1. 用环绕增强统一处理事务问题
要切入的代码
package com.obtk.dao;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import com.obtk.entitys.UserEntity;
import com.obtk.utils.MybatisUtil;
public class UserDaoImpl implements IUserDao {
public int saveUser(UserEntity theUser) throws RuntimeException{
// 4.得到session
SqlSession session = MybatisUtil.getSession();
System.out.println("程序代码中的对象哈希码:"+session.hashCode());
// 5.执行语句
int result = session.insert("user.saveOne", theUser);
// 添加完成可以取出启动增长的主键
System.out.println("添加成功!");
return result;
}
}
这里没有任何事务及异常处理,统一交给增强处理的代码完成
增强处理的代码如下:
package com.obtk.advise;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import com.obtk.entitys.UserEntity;
import com.obtk.utils.MybatisUtil;
@Aspect
public class AnnotationAdvise {
private static final Logger log = Logger.getLogger(AnnotationAdvise.class);
@Around("execution(* com.obtk.dao.*.saveUser(..))")
public Object arundAdvise(ProceedingJoinPoint jp){
Object result=null;
SqlSession session=MybatisUtil.getSession();
System.out.println("增强处理的代码对象哈希码:"+session.hashCode());
try {
result=jp.proceed();
session.commit();
} catch (Throwable e) {
session.rollback();
e.printStackTrace();
}finally{
MybatisUtil.closeSession();
}
return result;
}
}
配置
<?xml version="1.0" encoding="UTF-8"?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="userDao" class="com.obtk.dao.UserDaoImpl"></bean>
<!-- 增强处理的代码 -->
<bean id="aspectBean" class="com.obtk.advise.AnnotationAdvise"></bean>
<!-- 启动增强处理注解的支持 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
2 转账案例
简单模拟账户表
dao层代码
package com.obtk.dao;
import org.hibernate.Query;
import org.hibernate.Session;
public class AcctDaoImpl implements IAcctDao{
@Override
public void doPay(int payId, double amount) throws RuntimeException{
String hql="update AcctEntity set balance=balance-? where acctId=?";
Session session=HiberUtil.getSession();
Query qy=session.createQuery(hql);
qy.setParameter(0, amount);
qy.setParameter(1, payId);
int result=qy.executeUpdate();
if(result==0){
throw new RuntimeException("付款失败");
}
}
@Override
public void doReceive(int receiveId, double amount) {
String hql="update AcctEntity set balance2=balance+? where acctId=?";
Session session=HiberUtil.getSession();
Query qy=session.createQuery(hql);
qy.setParameter(0, amount);
qy.setParameter(1, receiveId);
int result=qy.executeUpdate();
if(result==0){
throw new RuntimeException("收款失败");
}
}
}
切入点不能配置在dao层
建立业务层biz
package com.obtk.biz;
import com.obtk.dao.IAcctDao;
public class AcctBiz {
private IAcctDao acctDao;
public void setAcctDao(IAcctDao acctDao) {
this.acctDao = acctDao;
}
//一个业务调用多个dao层的方法
public void doTransfer(int payId,int receiveId, double amount) throws RuntimeException{
acctDao.doPay(payId, amount);
acctDao.doReceive(receiveId, amount);
}
}
切入点配置在biz层
<?xml version="1.0" encoding="UTF-8"?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="userDao" class="com.obtk.dao.UserDaoImpl"></bean>
<bean id="acctDao" class="com.obtk.dao.AcctDaoImpl"></bean>
<bean id="acctBiz" class="com.obtk.biz.AcctBiz">
<property name="acctDao" ref="acctDao"></property>
</bean>
<!-- 增强处理的代码 -->
<bean id="aspectBean" class="com.obtk.advise.AnnotationAdvise"></bean>
<!-- 启动增强处理注解的支持 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
前两篇文章讲了各种增强处理,这篇文章再接着讲用注解定义增强以及切面编程的具体应用
一 用注解定义增强处理
除了实现Spring提供的特定接口,Spring还通过集成AspectJ实现了以注解的方式定义增强类,
大大减少了配置文件中的工作量。
增强处理代码
package com.obtk.advise;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import com.obtk.entitys.UserEntity;
@Aspect
public class AnnotationAdvise {
private static final Logger log = Logger.getLogger(AnnotationAdvise.class);
/*
@Before("execution(* com.obtk.dao.*.saveUser(..))")
public void beforMeth(JoinPoint jp) {
log.info("注解定义的前置增强==,调用者:"+jp.getTarget()
+",方法名:"+jp.getSignature().getName()
+",参数列表:"+Arrays.toString(jp.getArgs()));
}
@AfterReturning(pointcut="execution(* com.obtk.dao.*.saveUser(..))",returning="returnValue")
public void afterMeth(JoinPoint jp,Object returnValue){
log.info("注解定义的后置增强==,调用者:"+jp.getTarget()
+",方法名:"+jp.getSignature().getName()
+",参数列表:"+Arrays.toString(jp.getArgs())
+",返回值:"+returnValue);
}
@AfterThrowing(pointcut="execution(* com.obtk.dao.*.saveUser(..))",throwing="e")
public void afterPaoChu(JoinPoint jp,RuntimeException e){
log.info("注解定义的异常抛出增强==,调用者:"+jp.getTarget()
+",方法名:"+jp.getSignature().getName()
+",参数列表:"+Arrays.toString(jp.getArgs())
+",异常信息===>:"+e);
}
*/
//注解定义环绕增强
@Around("execution(* com.obtk.dao.*.saveUser(..))")
public Object arundAdvise(ProceedingJoinPoint jp){
log.info("注解定义的前置增强==,调用者:"+jp.getTarget()
+",方法名:"+jp.getSignature().getName()
+",参数列表:"+Arrays.toString(jp.getArgs()));
Object result=null;
try {
result=jp.proceed();
log.info("注解定义的后置增强==,调用者:"+jp.getTarget()
+",方法名:"+jp.getSignature().getName()
+",参数列表:"+Arrays.toString(jp.getArgs())
+",返回值:"+result);
} catch (Throwable e) {
log.info("注解定义的异常抛出增强==,调用者:"+jp.getTarget()
+",方法名:"+jp.getSignature().getName()
+",参数列表:"+Arrays.toString(jp.getArgs())
+",异常信息===>:"+e);
}
return result;
}
}
切入点代码
package com.obtk.dao;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import com.obtk.entitys.UserEntity;
import com.obtk.utils.MybatisUtil;
public class UserDaoImpl implements IUserDao{
public int saveUser(UserEntity theUser) {
System.out.println("方法执行前....");
int result=0;
SqlSession session=null;
try {
//4.得到session
session=MybatisUtil.getSession();
//5.执行语句
result=session.insert("user.saveOne", theUser);
session.commit();
//添加完成可以取出启动增长的主键
System.out.println("添加成功!");
} catch (Exception e) {
System.out.println("抛出了异常");
session.rollback();
throw new RuntimeException("发生了异常");
}finally{
MybatisUtil.closeSession();
}
return result;
}
}
配置
<?xml version="1.0" encoding="UTF-8"?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="userDao" class="com.obtk.dao.UserDaoImpl"></bean>
<!-- 增强处理的代码 -->
<bean id="aspectBean" class="com.obtk.advise.AnnotationAdvise"></bean>
<!-- 启动增强处理注解的支持 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
二 aop具体应用
1. 用环绕增强统一处理事务问题
要切入的代码
package com.obtk.dao;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import com.obtk.entitys.UserEntity;
import com.obtk.utils.MybatisUtil;
public class UserDaoImpl implements IUserDao {
public int saveUser(UserEntity theUser) throws RuntimeException{
// 4.得到session
SqlSession session = MybatisUtil.getSession();
System.out.println("程序代码中的对象哈希码:"+session.hashCode());
// 5.执行语句
int result = session.insert("user.saveOne", theUser);
// 添加完成可以取出启动增长的主键
System.out.println("添加成功!");
return result;
}
}
这里没有任何事务及异常处理,统一交给增强处理的代码完成
增强处理的代码如下:
package com.obtk.advise;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import com.obtk.entitys.UserEntity;
import com.obtk.utils.MybatisUtil;
@Aspect
public class AnnotationAdvise {
private static final Logger log = Logger.getLogger(AnnotationAdvise.class);
@Around("execution(* com.obtk.dao.*.saveUser(..))")
public Object arundAdvise(ProceedingJoinPoint jp){
Object result=null;
SqlSession session=MybatisUtil.getSession();
System.out.println("增强处理的代码对象哈希码:"+session.hashCode());
try {
result=jp.proceed();
session.commit();
} catch (Throwable e) {
session.rollback();
e.printStackTrace();
}finally{
MybatisUtil.closeSession();
}
return result;
}
}
配置
<?xml version="1.0" encoding="UTF-8"?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="userDao" class="com.obtk.dao.UserDaoImpl"></bean>
<!-- 增强处理的代码 -->
<bean id="aspectBean" class="com.obtk.advise.AnnotationAdvise"></bean>
<!-- 启动增强处理注解的支持 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
2 转账案例
简单模拟账户表
dao层代码
package com.obtk.dao;
import org.hibernate.Query;
import org.hibernate.Session;
public class AcctDaoImpl implements IAcctDao{
@Override
public void doPay(int payId, double amount) throws RuntimeException{
String hql="update AcctEntity set balance=balance-? where acctId=?";
Session session=HiberUtil.getSession();
Query qy=session.createQuery(hql);
qy.setParameter(0, amount);
qy.setParameter(1, payId);
int result=qy.executeUpdate();
if(result==0){
throw new RuntimeException("付款失败");
}
}
@Override
public void doReceive(int receiveId, double amount) {
String hql="update AcctEntity set balance2=balance+? where acctId=?";
Session session=HiberUtil.getSession();
Query qy=session.createQuery(hql);
qy.setParameter(0, amount);
qy.setParameter(1, receiveId);
int result=qy.executeUpdate();
if(result==0){
throw new RuntimeException("收款失败");
}
}
}
切入点不能配置在dao层
建立业务层biz
package com.obtk.biz;
import com.obtk.dao.IAcctDao;
public class AcctBiz {
private IAcctDao acctDao;
public void setAcctDao(IAcctDao acctDao) {
this.acctDao = acctDao;
}
//一个业务调用多个dao层的方法
public void doTransfer(int payId,int receiveId, double amount) throws RuntimeException{
acctDao.doPay(payId, amount);
acctDao.doReceive(receiveId, amount);
}
}
切入点配置在biz层
package com.obtk.advise; import org.apache.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.hibernate.Session; import org.hibernate.Transaction; import com.obtk.dao.HiberUtil; @Aspect public class AnnotationAdvise { @Around("execution(* com.obtk.biz.*.do*(..))") public Object arundAdvise(ProceedingJoinPoint jp){ Object result=null; Session session=HiberUtil.getSession(); System.out.println("增强处理的代码对象哈希码:"+session.hashCode()); Transaction tx=null; try { tx=session.beginTransaction(); result=jp.proceed(); tx.commit(); } catch (Throwable e) { System.out.println("我回滚了"); tx.rollback(); e.printStackTrace(); }finally{ HiberUtil.closeSession(); } return result; } }配置
<?xml version="1.0" encoding="UTF-8"?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="userDao" class="com.obtk.dao.UserDaoImpl"></bean>
<bean id="acctDao" class="com.obtk.dao.AcctDaoImpl"></bean>
<bean id="acctBiz" class="com.obtk.biz.AcctBiz">
<property name="acctDao" ref="acctDao"></property>
</bean>
<!-- 增强处理的代码 -->
<bean id="aspectBean" class="com.obtk.advise.AnnotationAdvise"></bean>
<!-- 启动增强处理注解的支持 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
相关文章推荐
- spring系列(四):切面编程(aop)2
- spring系列(三):切面编程(aop)1
- SpringBoot中使用AOP面向切面编程
- Java+spring切面编程(aop)spring控制反转(ioc)+hibenrate对象关系映射(ORM
- 【我看Spring】从一个简单的AOP示例看切面编程
- Spring AOP编程中--@aspect 标签,切面编程
- 使用Spring进行面向切面(AOP)编程
- 使用Spring进行切面(AOP)编程
- Spring AOP 面向切面编程 常见通知实现(前置,后置,环绕,异常)
- spring 面向切面编程AOP的原理
- 【我看Spring】从一个简单的AOP示例看切面编程
- 关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-使用工厂创建代理(Using the ProxyFactoryObject to create AOP proxies)
- Spring之AOP,面向切面编程
- 重新学习之spring第二个程序,配置AOP面向切面编程
- Spring Aop切面编程配置与实现
- 使用Spring进行切面(AOP)编程
- spring中面向切面编程AOP的简单应用
- Spring代码实例系列-07:Spring AOP面向切面,模拟实现事物控制
- Spring_aop切面编程
- 什么是SpringAop? 面向切面编程-----思想