一.增强
1.环境搭建
按照下图所示依次编写代码
1.dao层
接口
package com.xk.demo.dao;
import com.xk.demo.entity.User;
public interface UserDao {
/**
* 添加用户
* @param user 对象
* @return 影响行数
*/
int addUser(User user);
/**
* 修改用户
* @param user 对象
* @return 影响行数
*/
int updateUser(User user);
/**
* 删除用户
* @param userID 用户主键
* @return 影响行数
*/
int deleteUser(String userID);
}
实现类:
package com.xk.demo.dao.impl;
import com.xk.demo.dao.UserDao;
import com.xk.demo.entity.User;
public class UserDaoImpl implements UserDao {
/**
* 添加用户
*
* @param user 对象
* @return 影响行数
*/
public int addUser(User user) {
System.out.println("UserDaoImpl >>>>>>addUser ");
return 1;
}
/**
* 修改用户
*
* @param user 对象
* @return 影响行数
*/
public int updateUser(User user) {
System.out.println("UserDaoImpl >>>>>>updateUser ");
return 1;
}
/**
* 删除用户
*
* @param userID 用户主键
* @return 影响行数
*/
public int deleteUser(String userID) {
System.out.println("UserDaoImpl >>>>>>deleteUser ");
return 1;
}
}
2.业务层
接口:
package com.xk.demo.service;
import com.xk.demo.entity.User;
public interface UserService {
/**
* 添加用户
* @param user 对象
* @return 影响行数
*/
int addUser(User user);
/**
* 修改用户
* @param user 对象
* @return 影响行数
*/
int updateUser(User user);
/**
* 删除用户
* @param userID 用户主键
* @return 影响行数
*/
int deleteUser(String userID);
}
实现类
package com.xk.demo.service.impl;
import com.xk.demo.dao.UserDao;
import com.xk.demo.entity.User;
import com.xk.demo.service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao;
// 创建SET访问器 用于是spring 注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
/**
* 添加用户
*
* @param user 对象
* @return 影响行数
*/
public int addUser(User user) {
System.out.println("UserServiceImpl >>>>>>>>>>>addUser");
return userDao.addUser(user);
}
/**
* 修改用户
*
* @param user 对象
* @return 影响行数
*/
public int updateUser(User user) {
System.out.println("UserServiceImpl >>>>>>>>>>>updateUser");
return userDao.updateUser(user);
}
/**
* 删除用户
*
* @param userID 用户主键
* @return 影响行数
*/
public int deleteUser(String userID) {
System.out.println("UserServiceImpl >>>>>>>>>>>deleteUser");
return userDao.deleteUser(userID);
}
}
3.实体类
User.java
package com.xk.demo.entity;
public class User {
private String userCode;//用户编号
private String userName;//用户姓名
private String userPwd;//用户密码
public User() {
}
// public User(String userCode, String userName) {
// this.userCode = userCode;
// this.userName = userName;
// }
public User(String userCode, String userName, String userPwd) {
this.userCode = userCode;
this.userName = userName;
this.userPwd = userPwd;
}
public String getUserCode() {
return userCode;
}
public void setUserCode(String userCode) {
this.userCode = userCode;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
}
TestEnity.java 这个是用来测试用的代码
package com.xk.demo.entity;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* 用于测试IOC 注入 不同的类型数据
*/
public class TestEntity {
private String specialCharacter1; // 特殊字符值1
private String specialCharacter2; // 特殊字符值2
private User innerBean; // JavaBean类型
private List<String> list; // List类型
private String[] array; // 数组类型
private Set<String> set; // Set类型
private Map<String, String> map; // Map类型
private Properties props; // Properties类型
private String emptyValue; // 注入空字符串值
private String nullValue = "init value"; // 注入null值
public void setSpecialCharacter1(String specialCharacter1) {
this.specialCharacter1 = specialCharacter1;
}
public void setSpecialCharacter2(String specialCharacter2) {
this.specialCharacter2 = specialCharacter2;
}
public void setInnerBean(User user) {
this.innerBean = user;
}
public void setList(List<String> list) {
this.list = list;
}
public void setArray(String[] array) {
this.array = array;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProps(Properties props) {
this.props = props;
}
public void setEmptyValue(String emptyValue) {
this.emptyValue = emptyValue;
}
public void setNullValue(String nullValue) {
this.nullValue = nullValue;
}
public void showValue() {
System.out.println("特殊字符1:" + this.specialCharacter1);
System.out.println("特殊字符2:" + this.specialCharacter2);
System.out.println("内部Bean:" + this.innerBean.getUserName());
System.out.println("List属性:" + this.list);
System.out.println("数组属性[0]:" + this.array[0]);
System.out.println("Set属性:" + this.set);
System.out.println("Map属性:" + this.map);
System.out.println("Properties属性:" + this.props);
System.out.println("注入空字符串:[" + this.emptyValue + "]");
System.out.println("注入null值:" + this.nullValue);
}
}
3.增强类,位于aop下
package com.xk.demo.aop;
import org.apache.log4j.Logger;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
public class UserServiceLogger {
private static Logger log = Logger.getLogger(UserServiceLogger.class);
/**
* 前置增强
* JoinPoint : 目标方法的类名 方法名 参数列表....
*
* @param jp
*/
public void before(JoinPoint jp) {
log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
}
/**
* 后置增强
* JoinPoint : 目标方法的类名 方法名 参数列表....
* result :获取目标 方法的返回值
*
* @param jp
* @param result
*/
public void afterReturning(JoinPoint jp, Object result) {
log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法返回值:" + result);
}
}
配置
beans.xml
<?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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<!--将dao转换成bean-->
<bean id="userDao" class="com.xk.demo.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.xk.demo.service.impl.UserServiceImpl"></bean>
<!--增强类,交由Spring来管理,一般是对业务层进行增强-->
<bean id="userServiceLogger" class="com.xk.demo.aop.UserServiceLogger"></bean>
<!--
切入点 规则
public * addNewUser(entity.User): “*”表示匹配所有类型的返回值。
public void *(entity.User): “*”表示匹配所有方法名。
public void addNewUser(..): “..”表示匹配所有参数个数和类型。
* com.service.*.*(..):匹配com.service包下所有类的所有方法。
* com.service..*.*(..):匹配com.service包及其子包下所有类的所有方法
-->
<!--切面-->
<aop:config>
<!--
切入点:PointCut
expression="execution(访问修饰符 返回值类型 方法名( 包名.类名( 参数 ) ))"
.. 任何参数
com.xk.demo.service.*.* 第一个* 表示所有类 第二个*所有方法
-->
<aop:pointcut id="pointcut" expression="execution(* com.xk.demo.service.*.*(..) )"/>
<!-- 可以有很多个增强类 使用哪一个增强类 增强取决于 aop:aspect ref ="beanID"-->
<aop:aspect ref="userServiceLogger">
<!--
aop:before: 固定格式 前置增强
method 方法名称 (来自增强类)
pointcut-ref 切入点名称 aop:pointcut id="pointcut"
-->
<aop:before method="before" pointcut-ref="pointcut"></aop:before>
<!-- aop:after-returning: 固定格式 后置增强 -->
<!-- method 方法名称 (来自增强类) -->
<!-- pointcut-ref 切入点名称 aop:pointcut id="pointcut" -->
<!--returning 有返回值参数 (来自增强类) -->
<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
</aop:aspect>
</aop:config>
</beans>
测试:
import com.xk.demo.entity.User;
import com.xk.demo.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
int www = userService.addUser(new User("1", "www", "111"));
}
}
结果:
UserServiceImpl >>>>>>>>>>>addUser
UserDaoImpl >>>>>>addUser
2.前置增强和后置增强
注意,在上面的例子上已经实现了这两个增强,但是,debug一下
UserServiceImpl >>>>>>>>>>>addUser
UserDaoImpl >>>>>>addUser
发现并没有日志的输出和前置增强与后置增强,原因是因为log4j的配置出了问题
重新配置
# rootLogger是所有日志的根日志,修改该日志属性将对所有日志起作用
# 下面的属性配置中,所有日志的输出级别是info,输出源是con
log4j.rootLogger=info,con
# 定义输出源的输出位置是控制台
log4j.appender.con=org.apache.log4j.ConsoleAppender
# 定义输出日志的布局采用的类
log4j.appender.con.layout=org.apache.log4j.PatternLayout
# 定义日志输出布局
log4j.appender.con.layout.ConversionPattern=%d{MM-dd HH:mm:ss}[%p]%c%n -%m%n
测试结果
------------------------------
10-05 15:49:29[INFO]com.xk.demo.aop.UserServiceLogger
-调用 com.xk.demo.service.impl.UserServiceImpl@70f59913 的 addUser 方法。方法入参:[com.xk.demo.entity.User@4a194c39]
UserServiceImpl >>>>>>>>>>>addUser
UserDaoImpl >>>>>>addUser
10-05 15:49:29[INFO]com.xk.demo.aop.UserServiceLogger
-调用 com.xk.demo.service.impl.UserServiceImpl@70f59913 的 addUser 方法。方法返回值:1
3.异常抛出异常+最终增强
异常抛出增强,在目标方法抛出异常时织入增强处理
throwing后是形式参数
最终增强是在最后进行增强,类似于异常处理中的finally作用,销毁资源
1.编写aop增强类中的方法
package com.xk.demo.aop;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import java.util.Arrays;
//增强类
public class UserServiceLogger {
private static Logger log = Logger.getLogger(UserServiceLogger.class);
/**
* 前置增强
* JoinPoint : 目标方法的类名 方法名 参数列表....
*
* @param jp
*/
public void before(JoinPoint jp) {
log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
}
/**
* 后置增强
* JoinPoint : 目标方法的类名 方法名 参数列表....
* result :获取目标 方法的返回值
*
* @param jp
* @param result
*/
public void afterReturning(JoinPoint jp, Object result) {
log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法返回值:" + result);
}
/**
* 异常增强
* @param jp
* @param e
*/
public void afterThrowing(JoinPoint jp, RuntimeException e){
log.error("异常增强:"+jp.getSignature().getName()+" 方法发生异常:"+e);
}
/**
* 最终增强
* @param jp
*/
public void afterLogger(JoinPoint jp){
log.info("最终增强:"+jp.getSignature().getName()+" 方法结束执行");
}
}
2.配置beans.xml
<!--
切入点规则:
public * addNewUser(entity.User): “*”表示匹配所有类型的返回值。
public void *(entity.User): “*”表示匹配所有方法名。
public void addNewUser(..): “..”表示匹配所有参数个数和类型。
* com.service.*.*(..):匹配com.service包下所有类的所有方法。
* com.service..*.*(..):匹配com.service包及其子包下所有类的所有方法
-->
<!--切面-->
<aop:config>
<!--
切入点:PointCut
expression="execution(访问修饰符 返回值类型 方法名( 包名.类名( 参数 ) ))"
.. 任何参数
com.xk.demo.service.*.* 第一个* 表示所有类 第二个*所有方法
-->
<aop:pointcut id="pointcut" expression="execution(* com.xk.demo.service.*.*(..) )"/>
<!-- 可以有很多个增强类 使用哪一个增强类 增强取决于 aop:aspect ref ="beanID"
ref指向所引用的bean的id
-->
<aop:aspect ref="userServiceLogger">
<!--
aop:before: 固定格式 前置增强
method 方法名称 (来自增强类)
pointcut-ref 规定切入点名称 aop:pointcut id="pointcut"
-->
<aop:before method="before" pointcut-ref="pointcut"></aop:before>
<!--
后置增强
aop:after-returning: 固定格式 后置增强
method 方法名称 (来自增强类)
pointcut-ref 切入点名称 aop:pointcut id="pointcut"
returning 有返回值参数 (来自增强类)
-->
<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"></aop:after-returning>
<!--异常抛出增强,在目标方法抛出异常时织入增强处理
throwing后是形式参数
-->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"></aop:after-throwing>
<!--最终增强-->
<aop:after method="afterLogger" pointcut-ref="pointcut"></aop:after>
</aop:aspect>
</aop:config>
3.没有异常时进行测试
import com.xk.demo.dao.UserDao;
import com.xk.demo.entity.User;
import com.xk.demo.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) context.getBean("userService");
User user = new User("1","zzz","111111");
userService.addUser(user);
}
}
结果:
10-05 18:32:14[INFO]com.xk.demo.aop.UserServiceLogger
-前置增强:调用 com.xk.demo.service.impl.UserServiceImpl@373ebf74 的 addUser 方法。方法入参:[com.xk.demo.entity.User@626c44e7]
UserServiceImpl >>>>>>>>>>>addUser
UserDaoImpl >>>>>>addUser
10-05 18:32:14[INFO]com.xk.demo.aop.UserServiceLogger
-后置增强:调用 com.xk.demo.service.impl.UserServiceImpl@373ebf74 的 addUser 方法。方法返回值:1
10-05 18:32:14[INFO]com.xk.demo.aop.UserServiceLogger
-最终增强:addUser 方法结束执行
4.编写异常进行测试
在UserServiceImpl编写一个异常
public int addUser(User user) {
System.out.println(1/0);
System.out.println("UserServiceImpl >>>>>>>>>>>addUser");
return userDao.addUser(user);
}
测试的结果:
10-05 18:51:43[INFO]com.xk.demo.aop.UserServiceLogger
-前置增强:调用 com.xk.demo.service.impl.UserServiceImpl@373ebf74 的 addUser 方法。方法入参:[com.xk.demo.entity.User@626c44e7]
10-05 18:51:43[ERROR]com.xk.demo.aop.UserServiceLogger
-异常增强:addUser 方法发生异常:java.lang.ArithmeticException: / by zero
10-05 18:51:43[INFO]com.xk.demo.aop.UserServiceLogger
-最终增强:addUser 方法结束执行
java.lang.ArithmeticException: / by zero
at com.xk.demo.service.impl.UserServiceImpl.addUser(UserServiceImpl.java:25)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy7.addUser(Unknown Source)
at MyTest.test1(MyTest.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
由此可见,异常处理是在遇见异常的时候进行增强
4.环绕增强
- 目标方法前后都可织入增强处理
- 功能最强大的增强处理
- 可获取或修改目标方法的参数、返回值,可对它进行异常处理,甚至可以决定目标方法是否执行
1.aop增强类
package com.xk.demo.aop;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import java.util.Arrays;
//增强类
public class UserServiceLogger {
private static Logger log = Logger.getLogger(UserServiceLogger.class);
/**
* 前置增强
* JoinPoint : 目标方法的类名 方法名 参数列表....
*
* @param jp
*/
public void before(JoinPoint jp) {
log.info("前置增强:调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
}
/**
* 后置增强
* JoinPoint : 目标方法的类名 方法名 参数列表....
* result :获取目标 方法的返回值
*
* @param jp
* @param result
*/
public void afterReturning(JoinPoint jp, Object result) {
log.info("后置增强:调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法返回值:" + result);
}
/**
* 异常增强
* @param jp
* @param e
*/
public void afterThrowing(JoinPoint jp, RuntimeException e){
// System.out.println(1/0);
log.error("异常增强:"+jp.getSignature().getName()+" 方法发生异常:"+e);
}
/**
* 最终增强
* @param jp
*/
public void afterLogger(JoinPoint jp){
log.info("最终增强:"+jp.getSignature().getName()+" 方法结束执行");
}
//环绕增强
public Object aroundLogger(ProceedingJoinPoint joinPoint) throws Throwable{
//下面是目标方法的前面执行的处理
log.info("环绕增强:调用" + joinPoint.getTarget() + "的"
+ joinPoint.getSignature().getName() + "方法,方法参数是:"
+ Arrays.toString(joinPoint.getArgs()));
try {
//下面是目标方法之后进行的处理
Object result = joinPoint.proceed();
log.info("环绕增强:调用"+joinPoint.getTarget()+"的"+joinPoint.getSignature()+"方法,方法返回值:"+result);
return result;
} catch (Throwable e) {
log.error(joinPoint.getSignature().getName()+"方法发生异常"+e);
throw e;
} finally{
log.info(joinPoint.getSignature().getName()+" 方法结束执行 ");
}
}
}
beans.xml
<!--环绕增强-->
<aop:around method="aroundLogger" pointcut-ref="pointcut"></aop:around>
结果:
10-05 20:26:08[INFO]com.xk.demo.aop.UserServiceLogger
-前置增强:调用 com.xk.demo.service.impl.UserServiceImpl@59252cb6 的 addUser 方法。方法入参:[com.xk.demo.entity.User@6b3e12b5]
10-05 20:26:08[INFO]com.xk.demo.aop.UserServiceLogger
-环绕增强:调用com.xk.demo.service.impl.UserServiceImpl@59252cb6的addUser方法,方法参数是:[com.xk.demo.entity.User@6b3e12b5]
UserServiceImpl >>>>>>>>>>>addUser
UserDaoImpl >>>>>>addUser
10-05 20:26:08[INFO]com.xk.demo.aop.UserServiceLogger
-最终增强:addUser 方法结束执行
10-05 20:26:08[INFO]com.xk.demo.aop.UserServiceLogger
-环绕增强:调用com.xk.demo.service.impl.UserServiceImpl@59252cb6的int com.xk.demo.service.UserService.addUser(User)方法,方法返回值:1
10-05 20:26:08[INFO]com.xk.demo.aop.UserServiceLogger
-addUser 方法结束执行
10-05 20:26:08[INFO]com.xk.demo.aop.UserServiceLogger
-后置增强:调用 com.xk.demo.service.impl.UserServiceImpl@59252cb6 的 addUser 方法。方法返回值:1
二.注解
-
@Repository (bean的id):用于标注DAO层
@Service :用于标注业务层 -
下面两个要一起使用
@Autowired: 用于按照类型注入
@Qualifier -
@Component 用于标注通用业务,实现bean的定义
@Value(“admin”) 用于将固定的值注入到属性 -
@Resource(name = “userDao2”)用于按照名称注入
-
@Scope : 设置bean的作用域
-
@Aspect: 用于标注增强类
上文的配置过于繁琐,为了简化配置,推荐使用注解开发
使用步骤:
1.在配置文件中,引入一个context约束
beans.xml
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
2、配置扫描哪些包下的注解
<!--扫描包-->
<context:component-scan base-package="com.xk.demo.dao"></context:component-scan>
<context:component-scan base-package="com.xk.demo.service"></context:component-scan>
3、进行注解的标记
@Repository (bean的id):用于标注DAO层
@Service :用于标注业务层
下面两个要一起使用
@Autowired: 用于按照类型注入
@Qualifier
4.两种注入方式
类型注入
dao层
package com.xk.demo.dao.impl;
import com.xk.demo.dao.UserDao;
import com.xk.demo.entity.User;
import org.springframework.stereotype.Repository;
//类似于bean中的id
@Repository("userDao")
public class UserDaoImpl implements UserDao {
/**
* 添加用户
*
* @param user 对象
* @return 影响行数
*/
public int addUser(User user) {
System.out.println("UserDaoImpl >>>>>>addUser ");
return 1;
}
/**
* 修改用户
*
* @param user 对象
* @return 影响行数
*/
public int updateUser(User user) {
System.out.println("UserDaoImpl >>>>>>updateUser ");
return 1;
}
/**
* 删除用户
*
* @param userID 用户主键
* @return 影响行数
*/
public int deleteUser(String userID) {
System.out.println("UserDaoImpl >>>>>>deleteUser ");
return 1;
}
}
service层
package com.xk.demo.service.impl;
import com.xk.demo.dao.UserDao;
import com.xk.demo.entity.User;
import com.xk.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@Service("userService")
// 相当于配置文件中 <bean id="userService" class="当前注解的类"/>
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
// 创建SET访问器 用于是spring 注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
/**
* 添加用户
*
* @param user 对象
* @return 影响行数
*/
public int addUser(User user) {
System.out.println("UserServiceImpl >>>>>>>>>>>addUser");
return userDao.addUser(user);
}
/**
* 修改用户
*
* @param user 对象
* @return 影响行数
*/
public int updateUser(User user) {
System.out.println("UserServiceImpl >>>>>>>>>>>updateUser");
return userDao.updateUser(user);
}
/**
* 删除用户
*
* @param userID 用户主键
* @return 影响行数
*/
public int deleteUser(String userID) {
System.out.println("UserServiceImpl >>>>>>>>>>>deleteUser");
return userDao.deleteUser(userID);
}
}
测试结果:
10-05 20:49:28[INFO]com.xk.demo.aop.UserServiceLogger
-前置增强:调用 com.xk.demo.service.impl.UserServiceImpl@150ab4ed 的 addUser 方法。方法入参:[com.xk.demo.entity.User@4264b240]
10-05 20:49:28[INFO]com.xk.demo.aop.UserServiceLogger
-环绕增强:调用com.xk.demo.service.impl.UserServiceImpl@150ab4ed的addUser方法,方法参数是:[com.xk.demo.entity.User@4264b240]
UserServiceImpl >>>>>>>>>>>addUser
UserDaoImpl >>>>>>addUser
10-05 20:49:28[INFO]com.xk.demo.aop.UserServiceLogger
-最终增强:addUser 方法结束执行
10-05 20:49:28[INFO]com.xk.demo.aop.UserServiceLogger
-环绕增强:调用com.xk.demo.service.impl.UserServiceImpl@150ab4ed的int com.xk.demo.service.UserService.addUser(User)方法,方法返回值:1
10-05 20:49:28[INFO]com.xk.demo.aop.UserServiceLogger
-addUser 方法结束执行
10-05 20:49:28[INFO]com.xk.demo.aop.UserServiceLogger
-后置增强:调用 com.xk.demo.service.impl.UserServiceImpl@150ab4ed 的 addUser 方法。方法返回值:1
在dao下在编写一个实现类:
package com.xk.demo.dao.impl;
import com.xk.demo.dao.UserDao;
import com.xk.demo.entity.User;
import org.springframework.stereotype.Repository;
//类似于bean中的id
@Repository("userDao2")
public class UserDaoImpl2 implements UserDao {
/**
* 添加用户
*
* @param user 对象
* @return 影响行数
*/
public int addUser(User user) {
System.out.println("UserDaoImpl2 >>>>>>addUser ");
return 1;
}
/**
* 修改用户
*
* @param user 对象
* @return 影响行数
*/
public int updateUser(User user) {
System.out.println("UserDaoImpl2 >>>>>>updateUser ");
return 1;
}
/**
* 删除用户
*
* @param userID 用户主键
* @return 影响行数
*/
public int deleteUser(String userID) {
System.out.println("UserDaoImpl2 >>>>>>deleteUser ");
return 1;
}
}
测试:
import com.xk.demo.dao.UserDao;
import com.xk.demo.entity.User;
import com.xk.demo.service.UserService;
import com.xk.demo.service.impl.UserServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) context.getBean("userService");
User user = new User("1","zzz","111111");
userService.addUser(user);
}
}
发现报错,原因是获得userService不能确定使用那一个userDao
在UserServiceImpl里添加一个注解@Qualifier(“userDao2”),来确定使用
package com.xk.demo.service.impl;
import com.xk.demo.dao.UserDao;
import com.xk.demo.entity.User;
import com.xk.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@Service("userService")
// 相当于配置文件中 <bean id="userService" class="当前注解的类"/>
public class UserServiceImpl implements UserService {
@Autowired
@Qualifier("userDao2")
private UserDao userDao;
// 创建SET访问器 用于是spring 注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
/**
* 添加用户
*
* @param user 对象
* @return 影响行数
*/
public int addUser(User user) {
System.out.println("UserServiceImpl >>>>>>>>>>>addUser");
return userDao.addUser(user);
}
/**
* 修改用户
*
* @param user 对象
* @return 影响行数
*/
public int updateUser(User user) {
System.out.println("UserServiceImpl >>>>>>>>>>>updateUser");
return userDao.updateUser(user);
}
/**
* 删除用户
*
* @param userID 用户主键
* @return 影响行数
*/
public int deleteUser(String userID) {
System.out.println("UserServiceImpl >>>>>>>>>>>deleteUser");
return userDao.deleteUser(userID);
}
}
测试结果
10-05 21:13:01[INFO]com.xk.demo.aop.UserServiceLogger
-前置增强:调用 com.xk.demo.service.impl.UserServiceImpl@5ce33a58 的 addUser 方法。方法入参:[com.xk.demo.entity.User@75e01201]
10-05 21:13:01[INFO]com.xk.demo.aop.UserServiceLogger
-环绕增强:调用com.xk.demo.service.impl.UserServiceImpl@5ce33a58的addUser方法,方法参数是:[com.xk.demo.entity.User@75e01201]
UserServiceImpl >>>>>>>>>>>addUser
UserDaoImpl2 >>>>>>addUser
10-05 21:13:01[INFO]com.xk.demo.aop.UserServiceLogger
-最终增强:addUser 方法结束执行
10-05 21:13:01[INFO]com.xk.demo.aop.UserServiceLogger
-环绕增强:调用com.xk.demo.service.impl.UserServiceImpl@5ce33a58的int com.xk.demo.service.UserService.addUser(User)方法,方法返回值:1
10-05 21:13:01[INFO]com.xk.demo.aop.UserServiceLogger
-addUser 方法结束执行
10-05 21:13:01[INFO]com.xk.demo.aop.UserServiceLogger
-后置增强:调用 com.xk.demo.service.impl.UserServiceImpl@5ce33a58 的 addUser 方法。方法返回值:1
名称注入
@Resource(name = "userDao2") 用于按照名称进行注入
UserServiceImpl.java
package com.xk.demo.service.impl;
import com.xk.demo.dao.UserDao;
import com.xk.demo.entity.User;
import com.xk.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service("userService")
// 相当于配置文件中 <bean id="userService" class="当前注解的类"/>
public class UserServiceImpl implements UserService {
// @Autowired
//@Qualifier("userDao2")
@Resource(name = "userDao2")
private UserDao userDao;
// 创建SET访问器 用于是spring 注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
/**
* 添加用户
*
* @param user 对象
* @return 影响行数
*/
public int addUser(User user) {
System.out.println("UserServiceImpl >>>>>>>>>>>addUser");
return userDao.addUser(user);
}
/**
* 修改用户
*
* @param user 对象
* @return 影响行数
*/
public int updateUser(User user) {
System.out.println("UserServiceImpl >>>>>>>>>>>updateUser");
return userDao.updateUser(user);
}
/**
* 删除用户
*
* @param userID 用户主键
* @return 影响行数
*/
public int deleteUser(String userID) {
System.out.println("UserServiceImpl >>>>>>>>>>>deleteUser");
return userDao.deleteUser(userID);
}
}
通用型注解
@Component 用于标注通用业务,实现bean的定义
@Value("admin") 用于将固定的值注入到属性中
User.java
package com.xk.demo.entity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("user")
public class User {
@Value("admin")
private String userCode;//用户编号
@Value("admin")
private String userName;//用户姓名
@Value("admin")
private String userPwd;//用户密码
public User() {
}
/* public User(String userCode, String userName) {
this.userCode = userCode;
this.userName = userName;
}*/
public User(String userCode, String userName, String userPwd) {
this.userCode = userCode;
this.userName = userName;
this.userPwd = userPwd;
}
public String getUserCode() {
return userCode;
}
public void setUserCode(String userCode) {
this.userCode = userCode;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
}
测试:
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
System.out.println(user);
System.out.println(user.getUserCode());
System.out.println(user.getUserName());
System.out.println(user.getUserPwd());
}
结果:
com.xk.demo.entity.User@630cb4a4
admin
admin
admin
作用域注解:
scop : 设置bean的作用域
singleton:默认值 在spirng IOC 容器仅存在一个bean ,单例模式
prototype: 每次从容器中调用Bean时 ,都返回一个新的实例 例如 new xxxBean();
request: 每次HTTP请求 都会创建一个新的Bean,作用域仅限于WEBApplicationContext环境
session:同一个HTTP Session共享一个Bean,不同的Session使用不同的Bean,作用域仅限于WEBApplicationContext环境
global-session:一般用于Portlet应用环境,作用域仅限于WEBApplicationContext环境
User.java
package com.xk.demo.entity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component("user")
//每次调用getBean()都返回一个新的实例
@Scope("prototype")
public class User {
@Value("admin")
private String userCode;//用户编号
@Value("admin")
private String userName;//用户姓名
@Value("admin")
private String userPwd;//用户密码
public User() {
}
/* public User(String userCode, String userName) {
this.userCode = userCode;
this.userName = userName;
}*/
public User(String userCode, String userName, String userPwd) {
this.userCode = userCode;
this.userName = userName;
this.userPwd = userPwd;
}
public String getUserCode() {
return userCode;
}
public void setUserCode(String userCode) {
this.userCode = userCode;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
}
测试:
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
User user1 = (User) context.getBean("user");
User user2 = (User) context.getBean("user");
User user3 = (User) context.getBean("user");
System.out.println(user);
System.out.println(user.getUserCode());
System.out.println(user.getUserName());
System.out.println(user.getUserPwd());
}
用于标注增强类
使用@AspectJ,首先要保证所用的JDK 是5.0或以上版本
其次,要开启注解式的面向切面
beans.xml
<aop:aspectj-autoproxy />
改造增强类,UserServiceLogger.java
package com.xk.demo.aop;
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.Aspect;
import org.aspectj.lang.annotation.Before;
import java.util.Arrays;
//标注当前是增强类
@Aspect
public class UserServiceLogger {
private static Logger log = Logger.getLogger(UserServiceLogger.class);
/**
* 前置增强
* JoinPoint : 目标方法的类名 方法名 参数列表....
*
* @param jp
*/
/**
* 切入点规则:
* public * addNewUser(entity.User): “*”表示匹配所有类型的返回值。
* public void *(entity.User): “*”表示匹配所有方法名。
* public void addNewUser(..): “..”表示匹配所有参数个数和类型。
* * com.service.*.*(..):匹配com.service包下所有类的所有方法。
* * com.service..*.*(..):匹配com.service包及其子包下所有类的所有方法
* -->
*/
@Before("execution(* com.xk.demo.service.*.*(..) )")
public void before(JoinPoint jp) {
log.info("前置增强:调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
}
/**
* 后置增强
* JoinPoint : 目标方法的类名 方法名 参数列表....
* result :获取目标 方法的返回值
*
* @param jp
* @param result
*/
@AfterReturning(value = "execution(* com.xk.demo.service.*.*(..) )",returning = "result")
public void afterReturning(JoinPoint jp, Object result) {
log.info("后置增强:调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法返回值:" + result);
}
/**
* 异常增强
* @param jp
* @param e
*/
public void afterThrowing(JoinPoint jp, RuntimeException e){
System.out.println(1/0);
log.error("异常增强:"+jp.getSignature().getName()+" 方法发生异常:"+e);
}
/**
* 最终增强
* @param jp
*/
public void afterLogger(JoinPoint jp){
log.info("最终增强:"+jp.getSignature().getName()+" 方法结束执行");
}
//环绕增强
public Object aroundLogger(ProceedingJoinPoint joinPoint) throws Throwable{
//下面是目标方法的前面执行的处理
log.info("环绕增强:调用" + joinPoint.getTarget() + "的"
+ joinPoint.getSignature().getName() + "方法,方法参数是:"
+ Arrays.toString(joinPoint.getArgs()));
try {
//下面是目标方法之后进行的处理
Object result = joinPoint.proceed();
log.info("环绕增强:调用"+joinPoint.getTarget()+"的"+joinPoint.getSignature()+"方法,方法返回值:"+result);
return result;
} catch (Throwable e) {
log.error(joinPoint.getSignature().getName()+"方法发生异常"+e);
throw e;
} finally{
log.info(joinPoint.getSignature().getName()+" 方法结束执行 ");
}
}
}
这只是其中一种方法,简化它
在头部定义一个方法,在方法的身上来定义一个切入点
@Pointcut("execution(* com.xk.demo.service.*.*(..) )")
public void pointcut(){
}
package com.xk.demo.aop;
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.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import java.util.Arrays;
//标注当前是增强类
@Aspect
public class UserServiceLogger {
private static Logger log = Logger.getLogger(UserServiceLogger.class);
@Pointcut("execution(* com.xk.demo.service.*.*(..) )")
public void pointcut(){
}
/**
* 前置增强
* JoinPoint : 目标方法的类名 方法名 参数列表....
*
* @param jp
*/
/**
* 切入点规则:
* public * addNewUser(entity.User): “*”表示匹配所有类型的返回值。
* public void *(entity.User): “*”表示匹配所有方法名。
* public void addNewUser(..): “..”表示匹配所有参数个数和类型。
* * com.service.*.*(..):匹配com.service包下所有类的所有方法。
* * com.service..*.*(..):匹配com.service包及其子包下所有类的所有方法
* -->
*/
@Before("pointcut()")
public void before(JoinPoint jp) {
log.info("前置增强:调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
}
/**
* 后置增强
* JoinPoint : 目标方法的类名 方法名 参数列表....
* result :获取目标 方法的返回值
*
* @param jp
* @param result
*/
@AfterReturning(pointcut = "pointcut()",returning = "result")
public void afterReturning(JoinPoint jp, Object result) {
log.info("后置增强:调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法返回值:" + result);
}
/**
* 异常增强
* @param jp
* @param e
*/
public void afterThrowing(JoinPoint jp, RuntimeException e){
System.out.println(1/0);
log.error("异常增强:"+jp.getSignature().getName()+" 方法发生异常:"+e);
}
/**
* 最终增强
* @param jp
*/
public void afterLogger(JoinPoint jp){
log.info("最终增强:"+jp.getSignature().getName()+" 方法结束执行");
}
//环绕增强
public Object aroundLogger(ProceedingJoinPoint joinPoint) throws Throwable{
//下面是目标方法的前面执行的处理
log.info("环绕增强:调用" + joinPoint.getTarget() + "的"
+ joinPoint.getSignature().getName() + "方法,方法参数是:"
+ Arrays.toString(joinPoint.getArgs()));
try {
//下面是目标方法之后进行的处理
Object result = joinPoint.proceed();
log.info("环绕增强:调用"+joinPoint.getTarget()+"的"+joinPoint.getSignature()+"方法,方法返回值:"+result);
return result;
} catch (Throwable e) {
log.error(joinPoint.getSignature().getName()+"方法发生异常"+e);
throw e;
} finally{
log.info(joinPoint.getSignature().getName()+" 方法结束执行 ");
}
}
}
beans.xml
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!--扫描包-->
<context:component-scan base-package="com.xk.demo"></context:component-scan>
<aop:aspectj-autoproxy />
<!--将dao转换成bean
<bean id="userDao" class="com.xk.demo.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.xk.demo.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
-->
<!--增强类,交由Spring来管理,一般是对业务层进行增强-->
<bean id="userServiceLogger" class="com.xk.demo.aop.UserServiceLogger"></bean>
<!--
切入点规则:
public * addNewUser(entity.User): “*”表示匹配所有类型的返回值。
public void *(entity.User): “*”表示匹配所有方法名。
public void addNewUser(..): “..”表示匹配所有参数个数和类型。
* com.service.*.*(..):匹配com.service包下所有类的所有方法。
* com.service..*.*(..):匹配com.service包及其子包下所有类的所有方法
-->
</beans>
UserServiceLogger.java
package com.xk.demo.aop;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import java.util.Arrays;
//标注当前是增强类
@Aspect
public class UserServiceLogger {
private static Logger log = Logger.getLogger(UserServiceLogger.class);
@Pointcut("execution(* com.xk.demo.service.*.*(..) )")
public void pointcut(){
}
/**
* 前置增强
* JoinPoint : 目标方法的类名 方法名 参数列表....
*
* @param jp
*/
/**
* 切入点规则:
* public * addNewUser(entity.User): “*”表示匹配所有类型的返回值。
* public void *(entity.User): “*”表示匹配所有方法名。
* public void addNewUser(..): “..”表示匹配所有参数个数和类型。
* * com.service.*.*(..):匹配com.service包下所有类的所有方法。
* * com.service..*.*(..):匹配com.service包及其子包下所有类的所有方法
* -->
*/
@Before("pointcut()")
public void before(JoinPoint jp) {
log.info("前置增强:调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
}
/**
* 后置增强
* JoinPoint : 目标方法的类名 方法名 参数列表....
* result :获取目标 方法的返回值
*
* @param jp
* @param result
*/
@AfterReturning(pointcut = "pointcut()",returning = "result")
public void afterReturning(JoinPoint jp, Object result) {
log.info("后置增强:调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法返回值:" + result);
}
/**
* 异常增强
* @param jp
* @param e
*/
@AfterThrowing(pointcut = "pointcut()",throwing = "e")
public void afterThrowing(JoinPoint jp, RuntimeException e){
System.out.println(1/0);
log.error("异常增强:"+jp.getSignature().getName()+" 方法发生异常:"+e);
}
/**
* 最终增强
* @param jp
*/
@After("execution(* com.xk.demo.service.*.*(..) )")
public void afterLogger(JoinPoint jp){
log.info("最终增强:"+jp.getSignature().getName()+" 方法结束执行");
}
//环绕增强
@Around("execution(* com.xk.demo.service.*.*(..) )")
public Object aroundLogger(ProceedingJoinPoint joinPoint) throws Throwable{
//下面是目标方法的前面执行的处理
log.info("环绕增强:调用" + joinPoint.getTarget() + "的"
+ joinPoint.getSignature().getName() + "方法,方法参数是:"
+ Arrays.toString(joinPoint.getArgs()));
try {
//下面是目标方法之后进行的处理
Object result = joinPoint.proceed();
log.info("环绕增强:调用"+joinPoint.getTarget()+"的"+joinPoint.getSignature()+"方法,方法返回值:"+result);
return result;
} catch (Throwable e) {
log.error(joinPoint.getSignature().getName()+"方法发生异常"+e);
throw e;
} finally{
log.info(joinPoint.getSignature().getName()+" 方法结束执行 ");
}
}
}
三.Spring+Mybatis整合
步骤:
1.添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>20200924-Spring</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>spring01</module>
<module>Spring02-HelloSpring</module>
<module>spring03</module>
<module>spring04</module>
<module>spring05</module>
<module>spring06</module>
<module>spring07</module>
<module>spring08</module>
</modules>
<dependencies>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.10.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
</project>
四种整合方式
beans.xml
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!--扫描包-->
<context:component-scan base-package="com.xk.demo"></context:component-scan>
<bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/mybookshop"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!--创建sqlSessionFactory,通过sqlSessionFactory创建sqlSession
用这个sqlSessionFactory来创建当前的sqlSession
-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--传入数据源-->
<property name="dataSource" ref="datasource"></property>
<!--引入mybatis配置文件中的配置-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!--配置mybatis映射文件的位置
可能有多个
<property name="mapperLocations">
<list>
<value>classpath:com/xk/demo/mapper/**/*.xml</value>
</list>
</property>
-->
</bean>
<!--
方式1.使用模板,由Spring提供,方便我们的操作
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
通过构造函数注入
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
</bean>
-->
<!--
创建dao
<bean id="userMapperImpl" class="com.xk.demo.mapper.impl.UserMapperImpl">
//方式一:
// <property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>
//方式二,不注入模板,改注入sqlSessionFactory
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
-->
<!--
整合方式三,删除了实现类,但是sqlSessionFactory是必须要要的,那么怎么办
使用MapperFactoryBean整合
-->
<!--
名字按照模块去取
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
//MapperFactoryBean自己继承了SqlSessionDaoSupport,注入sqlSessionFactory
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
// MapperFactoryBean,需要mapper接口
<property name="mapperInterface" value="com.xk.demo.mapper.UserMapper"></property>
</bean>
方式3:
MapperFactoryBean注入给业务层
<bean id="userServiceImpl" class="com.xk.demo.service.impl.UserServiceImpl">
<property name="userMapper" ref="userMapper"></property>
</bean>
-->
<!--整合方式四,包扫描,最终版本
这种要配合注解来使用
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.xk.demo.mapper"></property>
</bean>
</beans>
1.整合方式1:
- 使用模板,由Spring提供,方便我们的操作
方式1.使用模板,由Spring提供,方便我们的操作
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
通过构造函数注入
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
</bean>
UserMapperImpl.java
创建当前接口实现类,并且声明sqlSessionTemplate,通过注入 注入sqlSessionTemplate
package com.xk.demo.mapper;
import com.xk.demo.pojo.Users;
import org.mybatis.spring.SqlSessionTemplate;
import java.util.List;
public class UserMapperImpl implements UserMapper {
private SqlSessionTemplate sqlSessionTemplate;
public List<Users> queryUser() {
return sqlSessionTemplate.selectList("com.xk.demo.UserMapper.queryUser");
}
}
测试:
package com.xk.test;
import com.xk.demo.pojo.Users;
import com.xk.demo.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class MyTest {
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) applicationContext.getBean("userServiceImpl");
List<Users> usersList = userService.queryUser();
for (Users users : usersList)
System.out.println(users.toString());
}
}
另一种方式:
删除dao层下的实现类,不在实现类里进行注入,而是在测试时进行注入
在测试类里进行这段代码
public class UserMapperImpl implements UserMapper {
private SqlSessionTemplate sqlSessionTemplate;
public List<Users> queryUser() {
return sqlSessionTemplate.selectList("com.xk.demo.UserMapper.queryUser");
}
}
2.整合方式二:
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--设置别名-->
<typeAliases>
<package name="com.xk.demo.pojo"/>
</typeAliases>
</configuration>
思考一个问题,我们肯定不只是有用户一个业务,如果有很多个业务,每一个都需要注入sqlSessionFactory,很麻烦!
UserMapperImpl.java
package com.xk.demo.mapper;
import com.xk.demo.pojo.Users;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
private SqlSessionTemplate sqlSessionTemplate;
public List<Users> queryUser() {
return sqlSessionTemplate.selectList("com.xk.demo.UserMapper.queryUser");
}
}
SqlSessionDaoSupport的源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.mybatis.spring.support;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.dao.support.DaoSupport;
import org.springframework.util.Assert;
public abstract class SqlSessionDaoSupport extends DaoSupport {
private SqlSessionTemplate sqlSessionTemplate;
public SqlSessionDaoSupport() {
}
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (this.sqlSessionTemplate == null || sqlSessionFactory != this.sqlSessionTemplate.getSqlSessionFactory()) {
this.sqlSessionTemplate = this.createSqlSessionTemplate(sqlSessionFactory);
}
}
protected SqlSessionTemplate createSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
public final SqlSessionFactory getSqlSessionFactory() {
return this.sqlSessionTemplate != null ? this.sqlSessionTemplate.getSqlSessionFactory() : null;
}
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
public SqlSession getSqlSession() {
return this.sqlSessionTemplate;
}
public SqlSessionTemplate getSqlSessionTemplate() {
return this.sqlSessionTemplate;
}
protected void checkDaoConfig() {
Assert.notNull(this.sqlSessionTemplate, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
}
}
UserMapperImpl.java
package com.xk.demo.mapper;
import com.xk.demo.pojo.Users;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
public List<Users> queryUser() {
return this.getSqlSession().selectList("com.xk.demo.UserMapper.queryUser");
}
}
beans.xml
<bean id="userMapperImpl" class="com.xk.demo.mapper.impl.UserMapperImpl">
//方式一:
// <property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>
//方式二,不注入模板,改注入sqlSessionFactory
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
3.整合方式三
实现类太麻烦
整合方式三,删除了实现类,但是sqlSessionFactory是必须要要的,那么怎么办
使用MapperFactoryBean整合
beans.xml
名字按照模块去取
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
//MapperFactoryBean自己继承了SqlSessionDaoSupport,注入sqlSessionFactory
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
// MapperFactoryBean,需要接口
<property name="mapperInterface" value="com.xk.demo.mapper.UserMapper"></property>
</bean>
//方式3:
// MapperFactoryBean注入给业务层
<bean id="userServiceImpl" class="com.xk.demo.service.impl.UserServiceImpl">
<property name="userMapper" ref="userMapper"></property>
</bean>
MapperFactoryBean的源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.mybatis.spring.mapper;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.session.Configuration;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.util.Assert;
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
private Class<T> mapperInterface;
private boolean addToConfig = true;
public MapperFactoryBean() {
}
public MapperFactoryBean(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
protected void checkDaoConfig() {
super.checkDaoConfig();
Assert.notNull(this.mapperInterface, "Property 'mapperInterface' is required");
Configuration configuration = this.getSqlSession().getConfiguration();
if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
try {
configuration.addMapper(this.mapperInterface);
} catch (Exception var6) {
this.logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", var6);
throw new IllegalArgumentException(var6);
} finally {
ErrorContext.instance().reset();
}
}
}
public T getObject() throws Exception {
return this.getSqlSession().getMapper(this.mapperInterface);
}
public Class<T> getObjectType() {
return this.mapperInterface;
}
public boolean isSingleton() {
return true;
}
public void setMapperInterface(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public Class<T> getMapperInterface() {
return this.mapperInterface;
}
public void setAddToConfig(boolean addToConfig) {
this.addToConfig = addToConfig;
}
public boolean isAddToConfig() {
return this.addToConfig;
}
}
4.整合方式四:最终版(推荐使用)
必须配合注解来使用
beans.xml
<!--整合方式四,包扫描,最终版本
这种要配合注解来使用
配置dao
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.xk.demo.mapper"></property>
</bean>
UserMapper.java
package com.xk.demo.mapper;
import com.xk.demo.pojo.Users;
import org.mybatis.spring.annotation.MapperScan;
import java.util.List;
//标注当前的dao层转换为bean,可写可不写,spring boot一定要写
@MapperScan
public interface UserMapper {
List<Users> queryUser();
}
UserServiceImpl.java
package com.xk.demo.service.impl;
import com.xk.demo.mapper.UserMapper;
import com.xk.demo.pojo.Users;
import com.xk.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("userServiceImpl")
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
public List<Users> queryUser() {
return userMapper.queryUser();
}
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
}
测试
package com.xk.test;
import com.xk.demo.pojo.Users;
import com.xk.demo.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class MyTest {
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) applicationContext.getBean("userServiceImpl");
List<Users> usersList = userService.queryUser();
for (Users users : usersList)
System.out.println(users.toString());
}
}
结果:
Users{Id=1, Name='shenbo', Address='Shenzhen', Phone='010-64324947', Mail='shenbo@163.com', UserStateId=1, IsOnLine=1, LoginId='申波', LoginPwd='shenbo', UserRoleId=1, Gender=1}
Users{Id=2, Name='Jing Jing', Address='Guangzhou', Phone='88888888', Mail='jingjing@sina.com', UserStateId=1, IsOnLine=1, LoginId='jingjing', LoginPwd='jingjing', UserRoleId=1, Gender=1}
Users{Id=3, Name='张三', Address='北京', Phone='010 5555555', Mail='bobo3@d.c', UserStateId=1, IsOnLine=1, LoginId='bobo', LoginPwd='123456', UserRoleId=2, Gender=1}
Users{Id=16, Name='user', Address='asd', Phone='11111111111', Mail='1@1.c', UserStateId=2, IsOnLine=0, LoginId='user', LoginPwd='111111', UserRoleId=1, Gender=0}
Users{Id=18, Name='admin', Address='admin', Phone='13456', Mail='123456@s.c', UserStateId=1, IsOnLine=0, LoginId='admin', LoginPwd='123456', UserRoleId=3, Gender=1}
Users{Id=22, Name='qiaximao', Address='上海市华夏路100号', Phone='13774210000', Mail='qiximao@163.com', UserStateId=1, IsOnLine=0, LoginId='恰嬉猫', LoginPwd='070115', UserRoleId=1, Gender=0}
Users{Id=26, Name='wangqiang', Address='北京软件大学', Phone='12334567891', Mail='wangqiang@163.com', UserStateId=1, IsOnLine=0, LoginId='王强', LoginPwd='991221', UserRoleId=1, Gender=1}
Users{Id=27, Name='手中沙', Address='深圳市', Phone='13520319988', Mail='jiyaoqin@163.com', UserStateId=1, IsOnLine=0, LoginId='ares', LoginPwd='123123', UserRoleId=2, Gender=1}
Users{Id=29, Name='风中雾', Address='辽宁锦州', Phone='13683123290', Mail='wuliping@263.net', UserStateId=1, IsOnLine=0, LoginId='30000', LoginPwd='tintin', UserRoleId=2, Gender=0}
四.事务
1.在UserMapper接口里编写一个方法
package com.xk.demo.mapper;
import com.xk.demo.pojo.Users;
import org.mybatis.spring.annotation.MapperScan;
import java.util.List;
//标注当前的dao层转换为bean,可写可不写,spring boot一定要写
@MapperScan
public interface UserMapper {
List<Users> queryUser();
int addUser(Users users);
}
2.UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xk.demo.mapper.UserMapper">
<select id="queryUser" resultType="com.xk.demo.pojo.Users">
select Id,Name,
Address,Phone,
Mail, UserStateId,
IsOnLine,LoginId,
LoginPwd, UserRoleId,
Gender
from users
</select>
<insert id="addUser" parameterType="Users">
insert into users
(Id,NAME,Address,Phone,Mail,UserStateId,IsOnLine,LoginId,LoginPwd,UserRoleId,Gender)
VALUES
(#{Id},#{NAME},#{Address},#{Phone},#{Mail},#{UserStateId},#{IsOnLine},#{LoginId},#{LoginPwd},#{UserRoleId},#{Gender})
</insert>
</mapper>
3.UserService
package com.xk.demo.service;
import com.xk.demo.pojo.Users;
import java.util.List;
public interface UserService {
List<Users> queryUser();
int addUser(Users users);
}
4.UserServiceImpl
package com.xk.demo.service.impl;
import com.xk.demo.mapper.UserMapper;
import com.xk.demo.pojo.Users;
import com.xk.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("userServiceImpl")
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
public List<Users> queryUser() {
return userMapper.queryUser();
}
public int addUser(Users users) {
return 1;
}
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
}
5.beanx.xml
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!--扫描包-->
<context:component-scan base-package="com.xk.demo"></context:component-scan>
<bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/mybookshop"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!--创建sqlSessionFactory,通过sqlSessionFactory创建sqlSession
用这个sqlSessionFactory来创建当前的sqlSession
-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--传入数据源-->
<property name="dataSource" ref="datasource"></property>
<!--引入mybatis配置文件中的配置-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!--配置mybatis映射文件的位置
可能有多个
<property name="mapperLocations">
<list>
<value>classpath:com/xk/demo/mapper/**/*.xml</value>
</list>
</property>
-->
</bean>
<!--
方式1.使用模板,由Spring提供,方便我们的操作
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
通过构造函数注入
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
</bean>
-->
<!--
创建dao
<bean id="userMapperImpl" class="com.xk.demo.mapper.impl.UserMapperImpl">
//方式一:
// <property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>
//方式二,不注入模板,改注入sqlSessionFactory
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
-->
<!--
整合方式三,删除了实现类,但是sqlSessionFactory是必须要要的,那么怎么办
使用MapperFactoryBean整合
-->
<!--
名字按照模块去取
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
//MapperFactoryBean自己继承了SqlSessionDaoSupport,注入sqlSessionFactory
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
// MapperFactoryBean,需要mapper接口
<property name="mapperInterface" value="com.xk.demo.mapper.UserMapper"></property>
</bean>
方式3:
MapperFactoryBean注入给业务层
<bean id="userServiceImpl" class="com.xk.demo.service.impl.UserServiceImpl">
<property name="userMapper" ref="userMapper"></property>
</bean>
-->
<!--整合方式四,包扫描,最终版本
这种要配合注解来使用
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.xk.demo.mapper"></property>
</bean>
<!--定义事务管理起-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"></property>
</bean>
<tx:advice id="txAdvice">
<!--定义规则-->
<tx:attributes>
<!--事务的传播机制-->
<tx:method name="query*" propagation="SUPPORTS"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="method" expression="execution(* com.xk.demo.service.*.*(..))"/>
<!--method处的规则引用到txAdvice-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="method"></aop:advisor>
</aop:config>
</beans>
6.测试:
package com.xk.test;
import com.xk.demo.pojo.Users;
import com.xk.demo.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class MyTest {
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) applicationContext.getBean("userServiceImpl");
List<Users> usersList = userService.queryUser();
for (Users users : usersList)
System.out.println(users.toString());
}
@Test
public void test2(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) applicationContext.getBean("userServiceImpl");
Users users = new Users();
users.setId(30);
users.setName("张三");
users.setAddress("陕西省西安市");
users.setPhone("11111111111");
users.setMail("11111@163.com");
users.setUserStateId(1);
users.setIsOnLine(1);
users.setLoginId("芜湖");
users.setLoginPwd("123456");
users.setUserRoleId(1);
users.setGender(1);
int row=userService.addUser(users);
System.out.println(row);
}
}
测试成功!
五.事务的传播机制
beans.xml
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"></property>
</bean>
<tx:advice id="txAdvice">
<!--定义规则-->
<tx:attributes>
<!--事务的传播机制-->
<tx:method name="query*" propagation="SUPPORTS"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="method" expression="execution(* com.xk.demo.service.*.*(..))"/>
<!--method处的规则引用到txAdvice-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="method"></aop:advisor>
</aop:config>
事务的隔离级别
- propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择。
- propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。
- propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。
- propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。
- propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。
- propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作
Spring 默认的事务传播行为是 PROPAGATION_REQUIRED,它适合于绝大多数的情况。
假设 ServiveX#methodX() 都工作在事务环境下(即都被 Spring 事务增强了),假设程序中存在如下的调用链:Service1#method1()->Service2#method2()->Service3#method3(),那么这 3 个服务类的 3 个方法通过 Spring 的事务传播机制都工作在同一个事务中。