一、面向切面编程(AOP)

1、AOP概述

1、面向切面编程(Aspect Oriented Programming,简称AOP)通过提供另一种思考程序结构的方式来补充面向对象编程 (Object Oriented Programming,简称OOP)。
2、OOP中模块化的关键单元是类,而在AOP中模块化的单元是切面。切面支持跨多种类型和对象的关注点(在AOP中通常称为“横切”关注点,例如事务管理)的模块化。
3、在OOP编程模式中,OOP将不同的业务对象的抽象成为一个个的类,不同的业务操作抽象成不同的方法,这样的好处是能更加清晰高效的逻辑单元划分!一个完整的业务逻辑就是调用不同的对象、方法来组合完成,这类似于流水线,核心业务和非核心业务都在里面,每一个步骤按照顺序执行。这样看来,业务逻辑之间的耦合关系非常严重,核心业务的代码之间通常需要手动嵌入大量非核心业务的代码,比如日志记录、事务管理。对于这种跨对象和跨业务的重复的、公共的非核心逻辑,OOP没有特别好的处理方式。
4、在AOP编程模式中,AOP能将不同业务流程中的相同的非核心业务逻辑从源代码中彻底抽离出来,形成一个独立的服务(比如日志记录、权限校验、异常处理、事物机制)。而当程序在编译或运行的时候,又能在不修改源代码的情况下,动态的选择在程序执行流程中的某些地方,比如方法运行前后,抛出异常时等,将这些非核心服务逻辑插入到核心代码逻辑中。
5、AOP技术让业务中的核心模块和非核心模块的耦合性进一步降低,实现了代码的复用,减少了代码量,提升开发效率,并有利于代码未来的可扩展性和可维护性。

2、AOP术语

1、Aspect(切面或方面):切入点(Pointcut)和该位置的通知(Advice)的结合,也可以说是被抽离出来的公共业务模块(比如:日志记录)。 对应Java代码中被@AspectJ注解标注的切面类或者在XML中配置的切面。
2、Join Point(连接点):程序执行时的一些特定位置或点位,这些点位就是可能被AOP框架拦截并织入代码的地方;连接点可能是类初始化、方法执行、方法调用、字段调用或处理异常等等,Spring只支持方法执行连接点
3、Point Cut(切入点):用来匹配要进行切入的Join point集合的表达式,通过切点表达式(pointcut expression,类似正则表达式)可以确定符合条件的连接点作为切入点。
4、Advice(通知):在连接点上执行的行为,提供了在AOP中需要在切入点(Pointcut)所选择的连接点(Join point)处进行扩展现有行为的手段。
5、Introduction(引介):一种特殊的通知,在不修改类代码的前提下,可以在运行期为类动态地添加一些额外的方法或属性。
6、Target Object(目标对象):需要被织入横切关注点的对象,即该对象是切入点选择的对象,需要被通知的对象,从而也可称为被通知对象;由于Spring AOP 通过代理模式实现,从而这个对象永远是被代理对象。
7、AOP Proxy(AOP代理):一个类被AOP织入增强后,就会产生一个代理对象。在Spring框架中,AOP代理是JDK动态代理或CGLIB代理。
8、Weaving(织入):是指把切面应用到目标对象来创建新的代理对象的过程。织入的时期可以是编译时织入(AspectJ),也可以使用运行时织入(Spring AOP)。

3、AOP中五种通知类型

1、Before advice(前置通知):在切入点方法之前执行的通知,但这个通知不能阻止切入点之前的执行流程,除非它抛出一个异常。
2、After Returning advice(后置通知):在切入点方法正常执行完成后要执行的通知(比如:一个方法没有抛出任何异常,正常返回)。
3、After Throwing advice(异常通知):在切入点方法抛出异常而退出时执行的通知。
4、After Finally advice(最终通知):无论切入点方法正常返回还是异常返回,都要执行的通知。
5、Around advice(环绕通知):可以在切入点方法调用前后完成自定义的行为。它也会选择是否继续执行或直接返回它自己的返回值或抛出异常来结束执行。

4、Spring AOP与AspectJ

1、AspectJ:是由Eclipse开源的一个AOP框架,基于Java平台,致力于提供了最完整的AOP实现方式,官方地址。
2、Spring AOP:是Spring提供的一个AOP框架。目的并不是提供最完整的AOP实现,相反,其目的是在AOP实现和SpringIOC之间提供紧密的集成,以帮助解决企业应用程序中的大多数常见的需求和问题(方法织入)。
3、Spring支持无缝集成AspectJ框架,因此也能使用AspectJ的全部功能;Spring2.0以后新增了对AspectJ切点表达式的支持,AspectJ框架在1.5版本时,通过JDK5的注解技术引入了一批注解,比如@AspectJ、@Pointcut、相关Advice注解,支持使用注解的声明式方式来定义切面,Spring同样支持使用和AspectJ相同的注解。
4、Spring AOP相比于AspectJ,它的学习难度更低,更容易上手。

5、织入方式

1、AspectJ属于静态织入:它使用了专门的称为AspectJ编译器 (ajc) 的编译器,在Java源码被编译的时候,就将切面织入到目标对象所属类的字节码文件中,并不会生成新的代理类字节码。因此,AspectJ在运行时不做任何事情,没有任何额外的开销,因为切面在类编译的时候就织入了。
2、Spring AOP属于动态织入:在运行时动态将要增强的代码织入到目标类中,是通过动态代理技术完成的,如Java JDK的动态代理(Proxy,底层通过反射实现)或者CGLIB的动态代理(底层通过继承实现),Spring AOP采用的就是基于运行时增强的代理技术。

6、JDK动态代理与CGLIB动态代理

1、JDK动态代理:JDK动态代理是由JDK提供的工具类Proxy实现的,动态代理类是在运行时生成指定接口的代理类,每个代理实例(实现需要代理的接口)都有一个关联的调用处理程序对象,此对象实现了InvocationHandler,最终的业务逻辑是在InvocationHandler实现类的invoke方法上。
2、CGLIB动态代理:是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。CGLIB通过继承的方式实现代理。
3、两者对比:
4、请参考设计模式中的代理模式

二、XML方式实现AOP

1、引入AOP依赖

1、Spring AOP需要引入两个依赖spring-aopaspectjweaver
2、可以直接引入spring-context依赖,因为它已经引入了其他核心的依赖spring-aop、spring-beans、spring-core、spring-expression等。
3、aspectjweaver用来解析切入点表达式的,因为Spring支持AspectJ的切入点表达式的语法。
<!--spring 核心组件所需依赖-->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId>
</dependency><!--用于解析AspectJ的切入点表达式语法-->
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.6</version>
</dependency>

2、添加AOP名称空间

1、Spring的原始配置文件仅支持IoC的配置,如果想要使用aop的XML配置,我们需要手动引入AOP名称空间(xmlns:aop),然后就能使用aop相关标签。
2、aop标签用于配置Spring中的所有AOP,包括Spring自己的基于代理的AOP框架和Spring与AspectJ AOP框架的集成。
<?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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"></beans>

3、简单示例

/*** @Date: 2023/1/6* 切面类* 注意:切面类需要注入到IOC容器中*/
@Component
public class LogAspect {/*** 前置通知*/public void before() {System.out.println("前置通知");}/*** 异常通知*/public void afterThrowing(Exception e) {System.out.println("异常通知,异常为:" + e.getMessage());}/*** 后置通知*/public void afterReturning(Object result) {System.out.println("后置通知,返回值为:" + result);}/*** 最终通知*/public void afterFinally() {System.out.println("最终通知");}/*** 环绕通知* 一定要有ProceedingJoinPoint类型的参数*/public Object around(ProceedingJoinPoint point) throws Throwable {System.out.println("环绕通知 --- 进入方法");// 需要手动放行方法,否则方法不会执行Object proceed = point.proceed();System.out.println("环绕通知 --- 退出方法");return proceed;}
}
/*** @Date: 2023/1/6* 目标类,也需要注入到IOC容器中*/
@Service
public class CalculateService {public Integer add(int i, int j) {return i + j;}public int sub(int i, int j) {return i + j;}public int multiply(int i, int j) {return i * j;}public double divide(int i, int j) {return i / j;}
}
<?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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 开启注解扫描 --><context:component-scan base-package="com.itan.aop.*" /><!-- aop的相关配置 --><aop:config><!-- 配置切面 --><aop:aspect ref="logAspect"><!-- 配置切点 --><aop:pointcut id="pointCutMethod" expression="execution(* com.itan.aop.service.*.*(..))"/><!-- 环绕通知 --><aop:around method="around" pointcut-ref="pointCutMethod" /><!-- 前置通知 --><aop:before method="before" pointcut-ref="pointCutMethod" /><!-- 异常通知,如果没有异常,将不会执行增强;throwing属性:用于设置通知第二个参数的的名称,类型是Throwable,它是所有错误和异常类的顶级父类 --><aop:after-throwing method="afterThrowing" pointcut-ref="pointCutMethod" throwing="e" /><!-- 后置通知,returning属性:用于设置后置通知的第二个参数的名称,类型是Object --><aop:after-returning method="afterReturning" pointcut-ref="pointCutMethod" returning="result" /><!-- 最终通知 --><aop:after method="afterFinally" pointcut-ref="pointCutMethod" /></aop:aspect></aop:config>
</beans>
/*** @Date: 2023/1/6* 测试类*/
public class AopTest1 {@Testpublic void test01() {// 通过配置文件创建容器对象ApplicationContext context = new ClassPathXmlApplicationContext("aop-config.xml");CalculateService calc = context.getBean(CalculateService.class);calc.add(2,3);System.out.println("==========================");calc.divide(2,0);}
}
/*** 运行结果:* 环绕通知 --- 进入方法* 前置通知* 环绕通知 --- 退出方法* 后置通知,返回值为:5* 最终通知* ==========================* 环绕通知 --- 进入方法* 前置通知* 异常通知,异常为:/ by zero* 最终通知*/

4、aop:config配置

1、aop相关的配置都写在<aop:config>标签中,用于实现Spring自动代理机制。
2、<aop:config>标签中可以包含<aop:pointcut>、<aop:advisor>、<aop:aspect>等标签,必须要按照该顺序声明这些标签
3、标签属性说明:

5、Spring AOP使用的代理方式

1、Spring AOP的默认代理方式是JDK动态代理,如果目标对象没有实现任何接口,则会选择使用CGLIB代理
2、如果实现了接口,可以通过proxy-target-class属性强制使用CGLIB代理。
/*** @Date: 2023/1/6* 接口类*/
public interface CalculateService {Integer add(int i, int j);int sub(int i, int j);int multiply(int i, int j);double divide(int i, int j);
}/*** @Date: 2023/1/6* 接口类实现类*/
@Service
public class CalculateServiceImpl implements CalculateService {public Integer add(int i, int j) {return i + j;}public int sub(int i, int j) {return i + j;}public int multiply(int i, int j) {return i * j;}public double divide(int i, int j) {return i / j;}
}
<!-- aop的相关配置 -->
<aop:config><aop:pointcut id="pointCutMethod" expression="execution(* com.itan.aop.*.*.*(..))" /><!-- 配置切面 --><aop:aspect ref="logAspect"><!-- 前置通知 --><aop:before method="before" pointcut-ref="pointCutMethod" /><!-- 最终通知 --><aop:after method="afterFinally" pointcut-ref="pointCutMethod" /></aop:aspect>
</aop:config>
@Test
public void test01() {// 通过配置文件创建容器对象ApplicationContext context = new ClassPathXmlApplicationContext("aop-config.xml");CalculateService calc = context.getBean(CalculateService.class);System.out.println(calc.getClass());calc.add(2,3);
}
/*** 运行结果:可以看到返回的是一个com.sun.proxy.$Proxy16类型的,说明默认使用的是JDK代理* class com.sun.proxy.$Proxy16* 前置通知* 最终通知*/
1、强制使用CGLIB代理,修改XML中的配置为<aop:config proxy-target-class="true">,运行程序,发现使用CGLIB代理。

2、目标对象不实现接口,将实现类去掉实现的接口CalculateService,运行程序,发现使用CGLIB代理。

三、切面相关配置

1、aop:aspect切面

1、<aop:aspect>标签用于配置切面,里面可以包含<aop:pointcut>、<aop:5种通知类型>等标签,必须要按照该顺序声明这些标签
2、标签属性说明:
/*** @Date: 2023/1/6* 第一个切面类*/
@Component
public class OrderAspect1 {/*** 前置通知*/public void before() {System.out.println("OrderAspect1前置通知");}/*** 后置通知*/public void afterReturning(Object result) {System.out.println("OrderAspect1后置通知,返回值为:" + result);}
}
/*** @Date: 2023/1/6* 第二个切面类*/
@Component
public class OrderAspect2 {/*** 前置通知*/public void before() {System.out.println("OrderAspect2前置通知");}/*** 后置通知*/public void afterReturning(Object result) {System.out.println("OrderAspect2后置通知,返回值为:" + result);}
}
<!-- aop的相关配置 -->
<aop:config><aop:pointcut id="pointCutMethod" expression="execution(* com.itan.aop.service.*.*(..))" /><!-- 配置切面1,order值设置为1000 --><aop:aspect ref="orderAspect1" order="1000"><!-- 前置通知 --><aop:before method="before" pointcut-ref="pointCutMethod" /><!-- 后置通知,returning属性:用于设置后置通知的第二个参数的名称,类型是Object --><aop:after-returning method="afterReturning" pointcut-ref="pointCutMethod" returning="result" /></aop:aspect><!-- 配置切面2,order值设置为100 --><aop:aspect ref="orderAspect2" order="100"><!-- 前置通知 --><aop:before method="before" pointcut-ref="pointCutMethod" /><!-- 后置通知,returning属性:用于设置后置通知的第二个参数的名称,类型是Object --><aop:after-returning method="afterReturning" pointcut-ref="pointCutMethod" returning="result" /></aop:aspect>
</aop:config>
@Test
public void test03() {// 通过配置文件创建容器对象ApplicationContext context = new ClassPathXmlApplicationContext("aop-config.xml");CalculateService calc = context.getBean(CalculateService.class);calc.add(2,3);
}
/*** 运行结果:可以看到切面的order值越小的前置通知先执行,后置通知最后执行* OrderAspect2前置通知* OrderAspect1前置通知* OrderAspect1后置通知,返回值为:5* OrderAspect2后置通知,返回值为:5*/

2、配置通知

1、<aop:aspect>切面标签中可以使用对应的5种通知标签:
2、5种通知标签属性说明:

3、环绕通知(特殊)

1、环绕通知是所有通知类型中功能最为强大的,能够全面地控制连接点,甚至可以控制是否执行连接点方法。
2、环绕通知使用<aop:around>标签配置,通常情况下,环绕通知都是独立使用的。
3、环绕通知的方法的第一个参数类型必须是ProceedingJoinPoint,它是JoinPoint的子接口,允许控制何时执行,是否执行连接点方法。
4、在环绕通知方法中需要明确调用ProceedingJoinPoint的proceed()方法来执行被代理的方法。方法proceed()的返回值就是连接点方法的返回值;通知方法的返回值就是外部调用切入点方法获取的最终返回值,如果没有返回值,那么外部调用切入点方法获取的最终返回值为null;环绕通知的返回值类型应该和切入点方法的返回值类型一致或者兼容

5、proceed方法中还可以传递一个数组,该数组就是切入点方法所需的参数。可以通过对ProceedingJoinPoint调用getArgs获取外部调用切入点方法时传递进来的参数数组,也可以在环绕通知的逻辑中自己设置参数。

4、JoinPoint

1、任何通知方法的第一个参数都可以声明为org.aspectj.lang.JoinPoint类型,JoinPoint是连接点方法的抽象,提供了访问当前被通知方法的目标对象,代理对象,方法参数等数据方法。
2、环绕通知的参数类型应该使用ProceedingJoinPoint,它是JoinPoint的一个实现;所有传入的JoinPoint的实际类型都是MethodInvocationProceedingJoinPoint
3、JoinPoint的相关方法说明:
方法名 说明
String toString() 返回连结点方法的签名,返回值和参数类型使用简单类名
String toShortString() 返回连结点方法的简要签名,省略返回值、参数类型、类路径
String toLongString() 返回连结点方法的完整签名,返回值和参数类型使用全路径名
Object getThis() 返回当前AOP代理对象
Object getTarget() 返回当前AOP目标对象
Object[] getArgs() 返回当前被通知方法传递的实际参数值数组
Signature getSignature() 返回当前连结点方法的签名
SourceLocation getSourceLocation() 返回连接点方法所在类文件中的位置,相关方法不支持
String getKind() 返回当前连接点的类型。Spring AOP为method-execution
StaticPart getStaticPart() 返回连接点静态部分,实际上就是返回当前JoinPoint对象
4、ProceedingJoinPoint相关方法说明:
方法名 说明
Object proceed() throws Throwable 执行目标方法,默认使用外部传递的参数
Object proceed(Object[] args) throws Throwable 执行目标方法,使用该方法传递的数组的值作为参数

5、aop:pointcut切点表达式

1、每一个通知中,都可以配置自己的切入点表达式,使用pointcut属性,很多时候切入点表达式都是一样的,可以使用<aop:pointcut>标签定义一个独立的切入点表达式,使得多个切面和通知通过pointcut-ref属性引用同一个切入点表达式。
2、<aop:pointcut>标签属性说明:
3、<aop:pointcut>标签作用位置:
/*** @Date: 2023/1/29* 切面类,切面类需要注入到IOC容器中*/
@Component
public class PointCutAspect {/*** 前置通知*/public void before() {System.out.println("前置通知");}/*** 最终通知*/public void afterFinally() {System.out.println("最终通知");}
}
/*** @Date: 2023/1/29* AOP目标切入点方法,需要注入到IOC容器中*/
@Component
public class AopTargetPointcut {public void target1() {System.out.println("目标切入点方法1");}public void target2() {System.out.println("目标切入点方法2");}
}
<!-- aop的相关配置 -->
<aop:config><!-- 配置一个所有切面的所有通知都能引用的表达式  aop:pointcut标签要定义在最前面 --><aop:pointcut id="p1" expression="execution(* com.itan.aop.pointcut.AopTargetPointcut.target1())" /><!-- 配置切面1 --><aop:aspect id="asp1" ref="pointCutAspect"><!-- 配置前置通知,引用切点表达式 --><aop:before method="before" pointcut-ref="p1" /></aop:aspect><!-- 配置切面2 --><aop:aspect id="asp2" ref="pointCutAspect"><!-- 配置只能是当前切面内部的所有通知都能引用的表达式 --><aop:pointcut id="p2" expression="execution(* com.itan.aop.pointcut.AopTargetPointcut.target2())" /><!-- 配置前置通知,引用切点表达式 --><aop:before method="before" pointcut-ref="p2" /><!--pointcut-ref 引用切面表达式--><aop:after method="afterFinally" pointcut-ref="p1" /></aop:aspect>
</aop:config>
@Test
public void test03() {// 通过配置文件创建容器对象ApplicationContext context = new ClassPathXmlApplicationContext("aop-config.xml");AopTargetPointcut atp = context.getBean(AopTargetPointcut.class);// 调用方法atp.target1();System.out.println("============================");atp.target2();
}
/*** 运行结果如下:调用target1方法会执行前置和后置通知,调用target2方法只会执行前置通知,与配置保持一致* 前置通知* 目标切入点方法1* 最终通知* ============================* 前置通知* 目标切入点方法2*/

四、切入点声明规则

1、切入点指示符

1、前面定义切点表达式时使用了大量的execution表达式,其中execution就是一个切入点指示符(pointcut designators,简称PCD),由于在Spring AOP中目前只支持方法调用作为连接点,所以Spring AOP的切入点指示符仅匹配方法执行的连接点。
2、Spring 5.x的AOP支持使用如下切入点指示符:
3、切入点表达式还支持如下通配符:
4、切入点表达式还支持运算符:

2、常用的execution指示符

1、execution的切入点表达式使用方法的签名来匹配切入点方法,是使用最多的一种方式。
2、语法格式说明:execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)

// 任意公共方法的执行:
execution(public * *(..))// 任何一个名字以“set”开始的方法的执行:
execution(* set*(..))// AccountService接口定义的任意方法的执行:
execution(* com.itan.service.AccountService.*(..))// MessagingConsumer类型及其子类型的headler方法
execution (* com.itan.aop.service.MessagingConsumer+.handle(..) )// 组合使用:通过匹配AOP的代理对象的类型是MessagingConsumer的,且方法是handle的任意参数的执行
this(com.itan.aop.service.MessagingConsumer) && execution(* handle(..))// 在service包中定义的任意方法的执行:
execution(* com.itan.service.*.*(..))// 在service包或其子包中定义的任意方法的执行:
execution(* com.itan.service..*.*(..))// 在service包中的任意连接点(在Spring AOP中只是方法执行):
within(com.itan.service.*)// 在service包或其子包中的任意连接点(在Spring AOP中只是方法执行):
within(com.itan.service..*)// 实现了AccountService接口的代理对象的任意连接点 (在Spring AOP中只是方法执行):
this(com.itan.service.AccountService// 实现AccountService接口的目标对象的任意连接点 (在Spring AOP中只是方法执行):
target(com.itan.service.AccountService)/*** 任何一个只接受一个参数,并且运行时所传入的参数是Serializable 接口的连接点(在Spring AOP中只是方法执行)* 'args'在绑定表单中更加常用; 请注意在例子中给出的切入点不同于execution(* *(java.io.Serializable)): * args版本只有在动态运行时候传入参数是Serializable时才匹配,而execution版本在方法签名中声明只有一个 Serializable类型的参数时候匹配。*/
args(java.io.Serializable)// 目标对象中有一个 @Transactional 注解的任意连接点 (在Spring AOP中只是方法执行)
@target(org.springframework.transaction.annotation.Transactional)// 任何一个目标对象声明的类型有一个 @Transactional 注解的连接点 (在Spring AOP中只是方法执行):
@within(org.springframework.transaction.annotation.Transactional) // 任何一个执行的方法有一个 @Transactional 注解的连接点 (在Spring AOP中只是方法执行)
@annotation(org.springframework.transaction.annotation.Transactional)// 任何一个只接受一个参数,并且运行时所传入的参数类型具有@Classified 注解的连接点(在Spring AOP中只是方法执行)
@args(com.itan.security.Classified)// 任何一个在名为'tradeService'的Spring bean之上的连接点 (在Spring AOP中只是方法执行)
bean(tradeService)// 任何一个在名字匹配通配符表达式'*Service'的Spring bean之上的连接点 (在Spring AOP中只是方法执行)
bean(*Service)

4、基于XML的AOP配置相关推荐

  1. spring中基于XML的AOP配置步骤

    spring中基于XML的AOP配置步骤 IAccountService.java package com.itheima.service;/*** 账户的业务层接口*/ public interfa ...

  2. 基于XML的AOP配置

    创建spring的配置文件并导入约束 此处要导入aop的约束 <?xml version="1.0" encoding="UTF-8"?> < ...

  3. Java spring基于XML的aop配置实现

    1.依赖包 2.文件结构 3.接口类ISomeService package com.buckwheats.test;public interface ISomeService {public voi ...

  4. 基于xml的方式配置AOP

    用基于 XML 的配置声明切面 除了使用 AspectJ 注解声明切面, Spring 也支持在 Bean 配置文件中声明切面. 这种声明是通过 aop schema 中的 XML 元素完成的. 正常 ...

  5. Spring框架----Spring的基于XML的AOP的实现

    导入依赖 <dependency><groupId>org.springframework</groupId><artifactId>spring-co ...

  6. 基于注解的 AOP 配置

    基于注解的 AOP 配置 bean.xml <?xml version="1.0" encoding="UTF-8"?> <beans xml ...

  7. html下拉菜单读取xml,基于XML的可配置Html下拉框的设计与实现

    (江西制造职业技术学院信息工程系,江西 南昌 330000) 摘 要:专门针对Web下拉框控件影响网页性能.不利于美工和维护等问题,通过比较Web下拉框与Html下拉框各自的利弊,提出一种基于XML实 ...

  8. 5、基于注解的AOP配置

    一.开启注解支持 1.概述 1.Spring AOP如同IoC一样支持基于XML和基于注解两种配置方式,基于注解所需的依赖和基于XML所需的依赖一致,其中spring-context包含了Spring ...

  9. spring框架的概述以及spring中基于XML的IOC配置——概念

    1.spring的概述     spring是什么     spring的两大核心     spring的发展历程和优势     spring体系结构 2.程序的耦合及解耦     曾经案例中问题   ...

最新文章

  1. 计算机应用专业能评自动化工程师吗,报考自动化控制工程师中级职称需要哪些条件?...
  2. 图论 ---- C. Nastya and Unexpected Guest(图上最短路dp + 01bfs)
  3. CRISP-DM (cross-industry standard process for data mining)跨行业数据挖掘过程标准
  4. DeepFaceLab 换脸
  5. caffe安装,编译(包括CUDA和cuDNN的安装),并训练,测试自己的数据(caffe使用教程)
  6. Python熊猫– GroupBy
  7. leetcood学习笔记-204-计算质数
  8. 阿里云mysql 分布式_MySQL大型分布式集群
  9. 简要描述内部连接和外部连接之间的区别_创新性的M12推拉式连接器推拉标准—跨制造商自动化技术的里程碑...
  10. C语言 vprintf 函数 - C语言零基础入门教程
  11. php system 执行失败,php执行system()函数没有任何反应
  12. 高通QFIL烧录错误解决方法
  13. svnserver 修改配置后重启
  14. sketchup生成面域插件_什么插件这么神奇,SketchUp一秒搞定99%异形建模
  15. Monte Carlo Tree Search (MCTS) 蒙特·卡罗尔树搜索
  16. 荣耀magicbookpro升级鸿蒙,魔法互传功能再升级 荣耀MagicBook 2019发布 售价3999元起...
  17. Android中Home键的监听和拦截
  18. 相机模型(针孔模型+畸变模型)
  19. 1.设计一个长方形的类,成员变量有长与宽,成员函数有求周长与面积,然后进行测试。要求有构造函数、析造函数和复制构造函数。
  20. AssetBundle.Unload(false/true)

热门文章

  1. 搭建springboot+mybatis+freemarker项目
  2. 利用水文分析提取山脊线山谷线
  3. itween的抛物线线性移动
  4. 洛谷 P3620 - P3621 数据备份、风铃、动物园(APIO 2007)
  5. 区块链的未来:“2020年起3-5年:国内区块链大规模商业应用将全面落地开花”
  6. 2022年中职网络空间安全国赛竞赛题解析仅代表自己的建议——2022年中职网络安全国赛竞赛试题2解析
  7. day56 JavaScript
  8. M480 EMAC驱动01-EMAC底层接口
  9. 【旅行】飘过江南(一)。
  10. 学计算机必学日语哪个学校,高中生学日语,大学可以学电脑类的专业吗?