一、初识AOP

  关于AOP的学习可以参看帮助文档:spring-3.2.0.M2\docs\reference\html目录下index.html的相关章节  
   1、AOP:Aspect-OrientedProgramming。AOP是OOP的补充,是GOF的延续。说到AOP,我们就不得不来提一下软件的纵向和横向问题。从纵向结构来看就是我们软件系统的各个模块,它主要负责处理我们的核心业务(例如商品订购、购物车查看);而从横向结构来看,我们几乎每个系统又包含一些公共模块(例如权限、日志模块等)。这些公共模块分布于我们各个核心业务之中(例如订购和查看商品明细的过程都需要检查用户权限、记录系统日志等)。这样一来不仅在开发过程中要处处关注公共模块的处理而且开发后维护起来也是十分麻烦。而有了AOP之后将应用程序中的商业逻辑同对其提供支持的通用服务进行分离,使得开发人员可以更多的关注核心业务开发。
 2、AOP术语

   切面(aspect):用来切插业务方法的类。
  连接点(joinpoint):是切面类和业务类的连接点,其实就是封装了业务方法的一些基本属性,作为通知的参数来解析。
  通知(advice):在切面类中,声明对业务方法做额外处理的方法。
  切入点(pointcut):业务类中指定的方法,作为切面切入的点。其实就是指定某个方法作为切面切的地方。
  目标对象(target object):被代理对象。
  AOP代理(aop proxy):代理对象。
  通知:
  前置通知(before advice):在切入点之前执行。
  后置通知(after returning advice):在切入点执行完成后,执行通知。
  环绕通知(around advice):包围切入点,调用方法前后完成自定义行为。
  异常通知(after throwing advice):在切入点抛出异常后,执行通知。
  AOP是基于代理模式,了解了jdk动态代理和cglib的用法,对我们学习大有裨益。

二、Spring AOP环境
  要在项目中使用Spring AOP 则需要在项目中导入除了springjar包之外,还有aspectjrt.jar,aspectjweaver.jar,aopalliance.jar,spring-aop-3.2.0.M2.jar和cglib.jar 。
   好了,前提工作准备完成,Spring提供了很多的实现AOP的方式:Spring接口方式,schema配置方式和注解等,好了废话不多说了,开始springaop学习之旅,这篇先以Spring接口的方式学起!

三、Spring接口方式实现AOP步骤
 
  利用Spring AOP接口实现AOP,主要是为了指定自定义通知来供spring AOP机制识别。主要接口:前置通知MethodBeforeAdvice,后置通知:AfterReturningAdvice,环绕通知:MethodInterceptor,异常通知:ThrowsAdvice。见例子代码:
 
步骤一、业务接口的编写
 //代理类接口,也是业务类接口<br>
 // 利用接口的方式,spring aop 将默认通过jdk动态代理来实现代理类<br>
 // 不利用接口,则spring aop 将通过cglib 来实现代理类

public interface IBaseBusiness {

// 用作代理的切入点方法
     public String delete(String obj)

//这方法不被切面切
    public String add(String obj);
  
   //这方法切不切呢?可以设置
   public String modify(String obj);
}

步骤二、业务类:

//业务类,也是目标对象

public class BaseBusiness implements IBaseBusiness {
    //切入点
     public String delete(String obj) {
       System.out.println("==========调用切入点:" + obj +"说:你敢删除我!===========\n");
       return obj + ":瞄~";
    }

publicString add(String obj) {
       System.out.println("================这个方法不能被切。。。==============\n");
       return obj + ":瞄~ 嘿嘿!";
    }

publicString modify(String obj) {
       System.out.println("=================这个也设置加入切吧====================\n");
       return obj + ":瞄改瞄啊!";
    }

}

步骤三、通知类:
   1、前置通知:

public class BaseBeforeAdvice implements MethodBeforeAdvice {

// method : 切入的方法 <br>
    //args :切入方法的参数 <br>
    // target :目标对象
   
   @Override
    public voidbefore(Method method, Object[] args, Object target) throwsThrowable {
       System.out.println("===========进入beforeAdvice()============\n");

System.out.print("准备在" + target + "对象上用");
       System.out.print(method + "方法进行对 '");
       System.out.print(args[0] + "'进行删除!\n\n");

System.out.println("要进入切入点方法了 \n");
    }

}

 2、后置通知:

public class BaseAfterReturnAdvice implements AfterReturningAdvice{
    //returnValue :切入点执行完方法的返回值,但不能修改<br>
    // method :切入点方法 <br>
    // args:切入点方法的参数数组 <br>
    // target :目标对象
    
   @Override
    public voidafterReturning(Object returnValue, Method method, Object[] args,Object target) throws Throwable {
       System.out.println("==========进入afterReturning()===========\n");
       System.out.println("切入点方法执行完了 \n");

System.out.print(args[0] + "在");
       System.out.print(target + "对象上被");
       System.out.print(method + "方法删除了");
       System.out.print("只留下:" + returnValue + "\n\n");
    }

}

  3、环绕通知:

public class BaseAroundAdvice implements MethodInterceptor {

// invocation :连接点
    
   @Override
    publicObject invoke(MethodInvocation invocation) throws Throwable {
       System.out.println("===========进入around环绕方法!=========== \n");

// 调用目标方法之前执行的动作
       System.out.println("调用方法之前: 执行!\n");

// 调用方法的参数
       Object[] args = invocation.getArguments();
       // 调用的方法
       Method method = invocation.getMethod();
       // 获取目标对象
       Object target = invocation.getThis();
       // 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行
       Object returnValue = invocation.proceed();

System.out.println("===========结束进入around环绕方法!===========\n");
      
       System.out.println("输出:" + args[0] + ";" + method + ";" + target +";" + returnValue + "\n");

System.out.println("调用方法结束:之后执行!\n");

return returnValue;
    }

}

 4、异常通知:

// 异常通知,接口没有包含任何方法。通知方法自定义

public class BaseAfterThrowsAdvice implements ThrowsAdvice {
    // 通知方法,需要按照这种格式书写
    // @param method
    //         可选:切入的方法
    //@param args
    //         可选:切入的方法的参数
    // @paramtarget
    //        可选:目标对象
    // @param throwable
    //  必填 : 异常子类,出现这个异常类的子类,则会进入这个通知。
   
    public voidafterThrowing(Method method, Object[] args, Object target,Throwable throwable) {
       System.out.println("删除出错啦");
    }

}

步骤四、定义指定切点:

//定义一个切点,指定对应方法匹配。来供切面来针对方法进行处理<br>
 // 继承NameMatchMethodPointcut类,来用方法名匹配

public class Pointcut extends NameMatchMethodPointcut {

privatestatic final long serialVersionUID = 3990456017285944475L;

@SuppressWarnings("rawtypes")
   @Override
    publicboolean matches(Method method, Class targetClass) {
       // 设置单个方法匹配
       this.setMappedName("delete");
       // 设置多个方法匹配
       String[] methods = { "delete", "modify" };
      
       //也可以用“ * ” 来做匹配符号
       // this.setMappedName("get*");
      
       this.setMappedNames(methods);

return super.matches(method, targetClass);
    }

}

步骤五、配置xml文件:
<?xml version="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xsi:schemaLocation="   
         http://www.springframework.org/schema/beans   
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
          <!-- 基于注解导入的-->       
        http://www.springframework.org/schema/context   
         http://www.springframework.org/schema/context/spring-context-3.0.xsd
       <!-- 基于aop导入的-->
        http://www.springframework.org/schema/aop   
         http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
   default->

<!--==============================利用spring自己的aop配置================================-->
   <!-- 声明一个业务类 -->
   <bean id="baseBusiness"class="aop.base.BaseBusiness" />
  
   <!-- 声明通知类 -->
   <bean id="baseBefore"class="aop.base.advice.BaseBeforeAdvice" />
   <bean id="baseAfterReturn"class="aop.base.advice.BaseAfterReturnAdvice"/>
   <bean id="baseAfterThrows"class="aop.base.advice.BaseAfterThrowsAdvice"/>
   <bean id="baseAround"class="aop.base.advice.BaseAroundAdvice" />

<!-- 指定切点匹配类 -->
   <bean id="pointcut"class="aop.base.pointcut.Pointcut" />

<!-- 包装通知,指定切点 -->
   <bean id="matchBeforeAdvisor"class="org.springframework.aop.support.DefaultPointcutAdvisor">
       <property name="pointcut">
           <ref bean="pointcut" />
       </property>
       <property name="advice">
           <ref bean="baseBefore" />
       </property>
   </bean>

<!-- 使用ProxyFactoryBean 产生代理对象-->
   <bean id="businessProxy"class="org.springframework.aop.framework.ProxyFactoryBean">
       <!-- 代理对象所实现的接口 ,如果有接口可以这样设置-->
       <propertyname="proxyInterfaces">
           <value>aop.base.IBaseBusiness</value>
       </property>

<!-- 设置目标对象 -->
       <property name="target">
           <ref local="baseBusiness" />
       </property>
       <!-- 代理对象所使用的拦截器 -->
       <propertyname="interceptorNames">
           <list>
               <value>matchBeforeAdvisor</value>
               <value>baseAfterReturn</value>
               <value>baseAround</value>
           </list>
       </property>
   </bean>
</beans>

步骤六、测试类:

public class Debug {

publicstatic void main(String[] args) {
       ApplicationContext context = newClassPathXmlApplicationContext("aop/schema_aop.xml");
       AspectBusiness business = (AspectBusiness)context.getBean("aspectBusiness");
       business.delete("猫");
    }

}

g、测试结果:运行下测试类,清晰明了。由于结果呈现太长就不贴了。
  具体的代码实现可以从代码注释中很容易理解接口方式的实现。结果也可想而知,前置方法会在切入点方法之前执行,后置会在切入点方法执行之后执行,环绕则会在切入点方法执行前执行同事方法结束也会执行对应的部分。主要是调用proceed()方法来执行切入点方法。来作为环绕通知前后方法的分水岭。然后在实现的过程中,有几点却是可以细揣摩一下的。
  可以看出在xml 配置businessProxy这个bean的时候,ProxyFactoryBean类中指定了,proxyInterfaces参数。这里我把他配置了IBaseBusiness接口。因为在项目开发过程中,往往业务类都会有对应的接口,以方便利用IOC解耦。但SpringAOP却也能支持没有接口的代理。这就是为什么需要导入cglib.jar的包了。看过spring的源码,知道在目标切入对象如果有实现接口,spring会默认使用jdk动态代理来实现代理类。如果没有接口,则会通过cglib来实现代理类。
  这个业务类现在有前置通知,后置通知,环绕三个通知同时作用,可能以及更多的通知进行作用。那么这些通知的执行顺序是怎么样的?就这个例子而言,同时实现了三个通知。在例子xml中,则显示执行before通知,然后执行around的前处理,执行切点方法,再执行return处理。最后执行around的后处理。经过测试,知道spring处理顺序是按照xml配置顺序依次处理通知,以队列的方式存放前通知,以压栈的方式存放后通知。所以是前通知依次执行,后通知到切入点执行完之后,从栈里在后进先出的形式把后通知执行。
  在实现过程中发现通知执行对应目标对象的整个类中的方法,如何精确到某个方法,则需要定义一个切点匹配的方式:spring提供了方法名匹配或正则方式来匹配。然后通过DefaultPointcutAdvisor来包装通知,指定切点。

 利用方式一的配置起来,可见代码还是非常的厚重的,定义一个切面就要定义一个切面类,然而切面类中,就一个通知方法,着实没有必要。所以Spring提供了,依赖aspectj的schema配置和基于aspectj注解方式。这两种方式非常简介方便使用,也是项目中普遍的使用方式。

一、通过Scheme配置实现AOP步骤(SpringAOP环境的环境与上篇博文

Spring接口方式相同)


  步骤一、编写业务类:

public class AspectBusiness {
   //切入点
   public String delete(String obj) {
       System.out.println("==========调用切入点:" + obj +"说:你敢删除我!===========\n");
       return obj + ":瞄~";
    }

publicString add(String obj) {
       System.out.println("================这个方法不能被切。。。==============\n");
       return obj + ":瞄~ 嘿嘿!";
    }

publicString modify(String obj) {
       System.out.println("=================这个也设置加入切吧====================\n");
       return obj + ":瞄改瞄啊!";
    }

}

步骤二、编写切面类:切面类中,包含了所有的通知

public class AspectAdvice {

//前置通知
  public void doBefore(JoinPoint jp) {
       System.out.println("===========进入before advice============\n");

System.out.print("准备在" + jp.getTarget().getClass() + "对象上用");
       System.out.print(jp.getSignature().getName() + "方法进行对 '");
       System.out.print(jp.getArgs()[0] + "'进行删除!\n\n");

System.out.println("要进入切入点方法了 \n");
    }

// 后置通知
    // @param jp
    //          连接点
    // @param result
    //        返回值
    
    public voiddoAfter(JoinPoint jp, String result) {
       System.out.println("==========进入after advice=========== \n");
       System.out.println("切入点方法执行完了 \n");

System.out.print(jp.getArgs()[0] + "在");
       System.out.print(jp.getTarget().getClass() + "对象上被");
       System.out.print(jp.getSignature().getName() + "方法删除了");
       System.out.print("只留下:" + result + "\n\n");
    }

// 环绕通知
    // @parampjp
    //         连接点
   
    publicobjectdoAround(ProceedingJoinPoint pjp) throws Throwable {
       System.out.println("===========进入around环绕方法!=========== \n");

// 调用目标方法之前执行的动作
       System.out.println("调用方法之前: 执行!\n");

// 调用方法的参数
       Object[] args = pjp.getArgs();
       // 调用的方法名
       String method = pjp.getSignature().getName();
       // 获取目标对象
       Object target = pjp.getTarget();
       // 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行
       Object result = pjp.proceed();

System.out.println("输出:" + args[0] + ";" + method + ";" + target +";" + result + "\n");
       System.out.println("调用方法结束:之后执行!\n");
    return result;
    }

//异常通知
  
    public voiddoThrow(JoinPoint jp, Throwable e) {
       System.out.println("删除出错啦");
    }

}

步骤四、配置文件的编写:

<?xml version="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xsi:schemaLocation="   
         http://www.springframework.org/schema/beans   
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
         http://www.springframework.org/schema/context   
         http://www.springframework.org/schema/context/spring-context-3.0.xsd
         http://www.springframework.org/schema/aop   
         http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
   default->

<!-- ==============================利用spring利用aspectj来配置AOP================================-->

<!-- 声明一个业务类 -->
   <bean id="aspectBusiness"class="aop.schema.AspectBusiness" />

<!-- 声明通知类 -->
   <bean id="aspectAdvice"class="aop.schema.advice.AspectAdvice"/>

<aop:config>
       <aop:aspect id="businessAspect"ref="aspectAdvice">
           <!-- 配置指定切入的对象 -->
           <aop:pointcut id="point_cut" expression="execution(*aop.schema.*.*(..))" />
           <!-- 只匹配add方法作为切入点
           <aop:pointcut id="except_add"expression="execution(* aop.schema.*.add(..))"/>
            -->

<!-- 前置通知 -->
           <aop:before method="doBefore"pointcut-ref="point_cut" />
           <!-- 后置通知 returning指定返回参数 -->
           <aop:after-returning method="doAfter"
               pointcut-ref="point_cut" returning="result" />
           <aop:around method="doAround"pointcut-ref="point_cut"/>
           <aop:after-throwing method="doThrow"pointcut-ref="point_cut" throwing="e"/>
       </aop:aspect>
   </aop:config>

</beans>

步骤五、测试类:

public class Debug {

publicstatic void main(String[] args) {
       ApplicationContext context = newClassPathXmlApplicationContext("aop/schema_aop.xml");
       AspectBusiness business = (AspectBusiness)context.getBean("aspectBusiness");
       business.delete("猫");
    }

}

一、简介
  
1、AOP用在哪些方面:AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制,异常处理等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
   2、AOP中的概念:
   Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是横切性关注点的抽象.

joinpoint(连接点):所谓连接点是指那些被拦截到的点(可以是方法、属性、或者类的初始化时机(可以是Action层、Service层、dao层))。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器)

Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义,也即joinpoint的集合.

Advice(通知):
所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知

Target(目标对象):代理的目标对象

Weave(织入)
:指将aspects应用到target对象并导致proxy对象创建的过程称为织入.

Introduction(引入):
在不修改类代码的前提下,Introduction可以在运行期为类动态地添加一些方法或Field.

  3、AOP带来的好处::降低模块的耦合度;使系统容易扩展;更好的代码复用性

二、通过注解方式实现Spring的AOPSpringAOP环境的环境与上篇博文

Spring接口方式相同)

注解在项目中已经到处都是了,撇开一些优劣不提,开发的便利性和可读性是非常的方便的。用来配置SpringAOP也非常简单便利
步骤一、编写业务类:

@Component   //使用自动注解的方式实例化并初始化该类
public class Business {
   // 切入点
   public String delete(String obj) {
       System.out.println("==========调用切入点:" + obj +"说:你敢删除我!===========\n");
       return obj + ":瞄~";
    }

publicString add(String obj) {
       System.out.println("================这个方法不能被切。。。==============\n");
       return obj + ":瞄~ 嘿嘿!";
    }

publicString modify(String obj) {
       System.out.println("=================这个也设置加入切吧====================\n");
       return obj + ":瞄改瞄啊!";
    }

}

步骤二、切面类:

// @Aspect : 标记为切面类
 // @Pointcut : 指定匹配切点集合
 // @Before : 指定前置通知,value中指定切入点匹配
 // @AfterReturning :后置通知,具有可以指定返回值
// @AfterThrowing :异常通知
 //注意:前置/后置/异常通知的函数都没有返回值,只有环绕通知有返回值
@Component   //首先初始化切面类
@Aspect     //声明为切面类,底层使用动态代理实现AOP
public class AspectAdvice {

//指定切入点匹配表达式,注意它是以方法的形式进行声明的。
    //即切点集合是:aop.annotation包下所有类所有方法
  //第一个*代表返回值类型

//如果要设置多个切点可以使用 || 拼接
 @Pointcut("execution(* aop.annotation.*.*(..))|| execution(*com.action.admin.*.*update*(..))")
    public voidanyMethod() {
    }

//前置通知
   //在切点方法集合执行前,执行前置通知
   @Before("execution(*aop.annotation.*.*(..))")
    public voiddoBefore(JoinPoint jp) {
       System.out.println("===========进入before advice============\n");

System.out.print("准备在" + jp.getTarget().getClass() + "对象上用");
       System.out.print(jp.getSignature().getName() + "方法进行对 '");
       System.out.print(jp.getArgs()[0] + "'进行删除!\n\n");

System.out.println("要进入切入点方法了 \n");
    }

//后置通知  
 @AfterReturning(value = "anyMethod()",returning = "result")
    public voiddoAfter(JoinPoint jp, String result) {
       System.out.println("==========进入after advice=========== \n");
       System.out.println("切入点方法执行完了 \n");

System.out.print(jp.getArgs()[0] + "在");
       System.out.print(jp.getTarget().getClass() + "对象上被");
       System.out.print(jp.getSignature().getName() + "方法删除了");
       System.out.print("只留下:" + result + "\n\n");
    }

// 环绕通知(##环绕通知的方法中一定要有ProceedingJoinPoint参数,与
   //Filter中的 doFilter方法类似)
   
   @Around("execution(*aop.annotation.*.*(..))")
    publicObject doAround(ProceedingJoinPointpjp) throws Throwable {
       System.out.println("===========进入around环绕方法!=========== \n");
 HttpSession session =ServletActionContext.getRequest().getSession();
    Emp login =(Emp)session.getAttribute("login");//ssh2整合后AOP也可以得到request、response、session等
       // 调用目标方法之前执行的动作
       System.out.println("调用方法之前: 执行!\n");

// 调用方法的参数
       Object[] args = pjp.getArgs();
       // 调用的方法名
       String method = pjp.getSignature().getName();
       // 获取目标对象(形如:com.action.admin.LoginAction@1a2467a)
       Object target = pjp.getTarget();
      //获取目标对象的类名(形如:com.action.admin.LoginAction)
     String targetName = pjp.getTarget().getClass().getName();
       // 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行
       Object result =pjp.proceed();//result的值就是被拦截方法的返回值

System.out.println("输出:" + args[0] + ";" + method + ";" + target +";" + result + "\n");
       System.out.println("调用方法结束:之后执行!\n");
     return result;
    }

// 异常通知
   
   @AfterThrowing(value= "execution(* aop.annotation.*.*(..))", throwing = "e")
    public voiddoThrow(JoinPoint jp, Throwable e) {
       System.out.println("删除出错啦");
    }

}

 步骤三、xml配置:

<?xml version="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xsi:schemaLocation="   
         http://www.springframework.org/schema/beans   
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
         http://www.springframework.org/schema/context   
         http://www.springframework.org/schema/context/spring-context-3.0.xsd
         http://www.springframework.org/schema/aop   
         http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
   default->

<context:component-scanbase-package="aop.annotation" />
    <!-- 打开aop 注解 -->
   <aop:aspectj-autoproxyproxy-target-class="true"/>

</beans>

步骤四、测试类:

public class Debug {

publicstatic void main(String[] args) {

ApplicationContext context = newClassPathXmlApplicationContext("aop/annotation_aop.xml");
       Business business = (Business) context.getBean("business");
       business.delete("猫");
    }

}

面向切面(AOP)之Spring接口方式 schema配置方式 aspectj注解方式相关推荐

  1. Spring学习笔记:3(面向切面AOP)

    AOP:Aspect Oriented Program(面向切面) 我们再回顾一下AOP的一些术语: 通知(Advice) 就是你想要的功能,也就是的安全.事物.日志等.先定义好,然后在想用的地方用一 ...

  2. SSM框架笔记08:初探Spring——采用配置类与注解方式

      初探Spring--采用配置类与注解方式   在上一讲的项目基础上继续.   不仅采用注解方式,而且用配置类替换Spring配置文件.   1.将xml_annotation包里的两个接口和四个类 ...

  3. Javaweb-Servlet总结(概述、接口使用、配置、获取请求方式、路径操作、Request对象、Response对象)

    文章目录 Servlet概述 Servlet核心接口和类 三种自定义Servlet接口的方法 1.实现Servlet接口 2.继承GenericServlet抽象类 3.继承HttpServlet抽象 ...

  4. spring,mybatis事务管理配置与@Transactional注解使用[转]

    spring,mybatis事务管理配置与@Transactional注解使用[转] spring,mybatis事务管理配置与@Transactional注解使用 概述 事务管理对于企业应用来说是至 ...

  5. spring,mybatis事务管理配置与@Transactional注解使用

    spring,mybatis事务管理配置与@Transactional注解使用 概述 事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性. Spring Framewor ...

  6. spring面向切面aop拦截器

    spring中有很多概念和名词,其中有一些名字不同,但是从功能上来看总感觉是那么的相似,比如过滤器.拦截器.aop等. 过滤器filter.spring mvc拦截器Interceptor .面向切面 ...

  7. 面向切面编程实现Nestjs接口Api数据缓存

    一.业务场景 在后端接口开发过程中,我们经常会谈论的话题,提高接口响应速度,前端接口调用后端接口响应时间的缩短,我们抛开数据库设计及后端代码的业务逻辑等问题.我们经常会听到说用redis做数据缓存,直 ...

  8. Spring总结四:IOC和DI 注解方式

    首先我们要了解注解和xml配置的区别: 作用一样,但是注解写在Bean的上方来代替我们之前在xml文件中所做的bean配置,也就是说我们使用了注解的方式,就不用再xml里面进行配置了,相对来说注解方式 ...

  9. Spring第七弹—依赖注入之注解方式注入及编码解析@Resource原理

        注入依赖对象可以采用手工装配或自动装配,在实际应用中建议使用手工装配,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果. 手工装配依赖对象  手工装配依赖对象,在这种方式中又有两种编 ...

最新文章

  1. 为什么不提供离线Blog管理工具呢?
  2. SeetaFace2 测试
  3. 让Team Exploer自动登录TFS
  4. 【Flask】数据的CRUD之更新和删除操作
  5. Python执行系统命令的方法 os.system(),os.popen(),commands
  6. Python中map的使用方法
  7. Django Rest Framework源码剖析(七)-----分页
  8. ADT(Android) — Eclipse开发NOX夜神安卓模拟器如何进行横竖屏切换
  9. 定推【好处】篇,牵手定推,好处多多
  10. python 指定时间运行代码
  11. 【软件工程】软件测试报告——软件测试说明书
  12. SQL盲注及python脚本编写
  13. 五分钟解读“大数据”
  14. qt中采用G.729A进行网络语音通话实验程序
  15. win10 .Net Runtime Optimization Service占用大量CPU资源解决方法
  16. Android drawable.setBounds()+设置RadioButton的图片大小和位置
  17. 人工智能(强化学习)
  18. win10下pytorch-gpu安装以及CUDA详细安装过程
  19. Hadoop 2.7.2 分布式集群搭建-操作指南(不断更新)
  20. 【Matlab】input 请求用户输入

热门文章

  1. hdu4604 不错的子序列问题
  2. 操作系统原理第五章:CPU调度
  3. 【Linux 内核】进程管理 ( 进程状态 | 进程创建 | 进程终止 | 调用 exit 系统调用函数主动退出 | main 函数返回自动退出 | kill 杀死进程 | 执行异常退出 )
  4. 【错误记录】IntelliJ IDEA 编译 Groovy 报错 ( GroovyRuntimeException: This script or class could not be run. )
  5. 【Android 逆向】整体加固脱壳 ( 脱壳点简介 | 修改系统源码进行脱壳 )
  6. 【错误记录】Android Studio 编译报错 ( Could not determine java version from ‘11.0.8‘. | 仅做参考 | 没有解决实际问题 )
  7. 【字符串】字符串查找 ( 蛮力算法 )
  8. 【商务智能】商务智能 ( 概念 | 组成 | 过程 )
  9. 项目实战---模拟亿邦动力网
  10. 爬虫五 Beautifulsoup模块详细