增强+注解+Spring和Mybatis的整合+事务+事务的传播级别

一.增强

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 的事务传播机制都工作在同一个事务中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值