spring-第十七篇之spring AOP基于注解的零配置方式
1、基于注解的零配置方式
Aspect允许使用注解定义切面、切入点和增强处理,spring框架可以识别并根据这些注解来生成AOP代理。spring只是用了和AspectJ 5一样的注解,但并没有使用AspectJ的编译器或者织入器,底层依然使用的是spring AOP。
为了启用spring对@Aspect切面配置的支持,并保证spring容器中的目标bean被一个或多个切面自动增强,必须在spring配置文件中加入以下代码:
引入命名空间:xmlns:aop="http://www.springframework.org/schema/aop"
引入元素:
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
启用对@Aspect注解的支持:<aop:aspectj-autoproxy/>
如果不打算使用spring的XML Schema配置方式,则应该在spring配置文件中增加如下代码来启用@AspectJ的支持。
<!-- 完全不打算使用spring的xml schema配置方式使用spring AOP,即bean的注册也使用注解的形式。应该加入如下代码 ,AnnotationAwareAspectJAutoProxyCreator是一个bean后处理器,该bean后处理器将会为容器中的所有bean生成AOP代理--><bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>
为了在spring应用中启动@AspectJ的支持,还需要在应用的类加载路径下增加两个AspectJ库:aspectjweaver.jar和aspectjrt.jar,除此之外,spring AOP还依赖aopalliance.jar。
2、定义切面bean
使用@Aspect注解切面bean。
3、定义切入点
1》切入点的定义包含两部分:
1>定义切入点表达式:指定与哪些方法匹配。切入点表达式使用@Pointcut注解标注。
2>定义名字和任意参数的方法签名:方法签名方法体通常为空,返回值必须为void。签名方法有访问控制符,如private只能是本切入面中使用该切入点,与Java的访问控制符意义差不多。
切入点的定义:
package com.lfy.aspect;import org.aspectj.lang.annotation.Pointcut;/*** 切入点组合连接符有&&、||、!* @author lfy**/ public class PointcutUtil {//使用@Pointcut注解定义切入点,public控制着切入点的访问权限@Pointcut("execution(int com.lfy.impl.HelloImpl.fourAdviceGetParamer(..))")public void myPointcut() {} }
使用举例:
@Before("execution(int com.lfy.impl.HelloImpl.fourAdviceGetParamer(..)) || PointcutUtil.myPointcut()")public void authority(JoinPoint jp) {System.out.println("FourAdviceGetParamerAspect.Before模拟执行权限检查");//返回被织入增强的目标方法System.out.println("被织入的目标方法是: "+jp.getSignature().getName());System.out.println("被织入的目标方法的参数: "+Arrays.toString(jp.getArgs()));System.out.println("被织入增强处理的目标对象为: "+jp.getTarget());System.out.println("<---------------->");}
2》切入点指示符
定义切入点的时候,execution就是一个切入点指示符。spring AOP仅支持部分AspectJ的切入点指示符。spring AOP支持的切入点指示符有:
1>excution:用于匹配执行方法的连接点。其表达式格式如下。
excution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?),对各部分的解析如下。
modifiers-pattern:指定方法的修饰符,支持通配符,该部分可以省略。
ret-type-pattern:指定方法的返回值类型,支持通配符,可以使用“*”通配符来匹配所有的返回值类型。
declaring-type-pattern:指定方法所属的类,支持通配符,该部分可以省略。
name-pattern:指定匹配指定的方法名,支持通配符,可以使用“*”通配符来匹配所有方法。
param-pattern:指定方法声明中的形参列表,支持两个通配符,即“*”和“..”,其中“*”代表一个任意类型的参数,“..”代表0个或多个任意类型的参数。
throws-pattern:指定目标方法声明抛出的异常类型,支持通配符,该部分可以省略。
2>within:用于限定匹配特定类型的连接点,当使用spring AOP的时候,只匹配方法执行的连接点(spring AOP支持方法连接)。
//在com.lfy.bean包中的任意连接点 within(com.lfy.bean.*) //在com.lfy.bean包或其子包中的任意连接点 within(com.lfy.bean..*)
3>this:用于限定AOP代理必须是指定类型的实例,匹配该对象的所有连接点。当使用spring AOP的时候,只能匹配方法执行的连接点(spring AOP支持方法连接)。
//匹配实现了com.lfy.bean.Person接口的AOP代理的所有连接点 //在spring AOP中只是方法执行的连接点 this(com.lfy.bean.Person)
4>target:用于限定目标对象必须是指定类型的实例,匹配该对象的所有连接点。当使用spring AOP的时候,只能匹配方法执行的连接点(spring AOP支持方法连接)。
//匹配实现了com.lfy.bean.Person接口的目标对象的所有连接点 //在spring AOP中只是方法执行的连接点 target(com.lfy.bean.Person)
5>args:用于对连接点的参数类型和数量进行限制,要求参数类型和数量是指定的数量和类型的实例。当使用spring AOP的时候,只能匹配方法执行的连接点(spring AOP支持方法连接)。
//匹配只接受一个参数,且传入的参数类型是Serializable的所有连接点 //在spring AOP中只是方法执行的连接点 args(java.io.Serializable)
6>bean:spring AOP提供的限制只匹配指定bean实例内的连接点(spring AOP支持方法连接)。定义bean表达式时需要传入bean的id或name,表示只匹配该bean实例内的连接点,支持使用“*”通配符。
//匹配com.lfy.impl.Chinese bean实例内方法执行的连接点 bean(com.lfy.impl.Chinese) //匹配名字以Impl结尾的bean实例内方法执行的连接点 bean(*impl)
3》组合切入点表达式
spring支持使用如下3个逻辑运算符来组合切入点表达式:
1>&&:要求连接点同时匹配两个切入点表达式,即切入点表达式做逻辑与。
2>||:连接点匹配任意一个表达式,即表达式逻辑或。
3>!:连接点不匹配指定的切入点表达式,即切入点表达式逻辑非。
@Before("execution(int com.lfy.impl.HelloImpl.fourAdviceGetParamer(..)) || PointcutUtil.myPointcut()")public void authority(JoinPoint jp) {System.out.println("FourAdviceGetParamerAspect.Before模拟执行权限检查");//返回被织入增强的目标方法System.out.println("被织入的目标方法是: "+jp.getSignature().getName());System.out.println("被织入的目标方法的参数: "+Arrays.toString(jp.getArgs()));System.out.println("被织入增强处理的目标对象为: "+jp.getTarget());System.out.println("<---------------->");}
4、定义增强处理
1》Before增强处理
使用@Before注解一个切面方法,该方法作为Before增强处理,可以指定一个value属性,value属性的值就是切入点(可以是一个已有的切入点,也可以是表达式)。Before增强处理在目标方法前执行,不会影响目标方法的执行,除非Before增强抛异常了,则会阻止目标方法的执行
@Before("execution(int com.lfy.impl.HelloImpl.fourAdviceGetParamer(..)) || PointcutUtil.myPointcut()")public void authority(JoinPoint jp) {System.out.println("FourAdviceGetParamerAspect.Before模拟执行权限检查");//返回被织入增强的目标方法System.out.println("被织入的目标方法是: "+jp.getSignature().getName());System.out.println("被织入的目标方法的参数: "+Arrays.toString(jp.getArgs()));System.out.println("被织入增强处理的目标对象为: "+jp.getTarget());System.out.println("<---------------->");}
2》AfterReturning增强处理
使用@AfterReturning注解一个切面方法,AfterReturning增强处理将在目标方法正常完成后被织入。可以访问到目标方法的返回值,但不可以修改目标方法的返回值。
/*** 该注解可以指定pointcut/value,returning这两个常用的属性:<br>* 1>>pointcut/value:用于指定切入点表达式,可以是已有的切入点,也* 可以直接指定表达式。pointcut指定的值会覆盖value指定的值。<br>* 2>>returning:指定一个形参名,用于表示增强处理方法中可定义与此同名* 的形参,该形参可用于访问目标方法的返回值。除此之外,在增强处理方法上定义* 的该形参(代表目标方法的返回值)指定的类型,将限制目标方法必须返回该类型* 的值或没有返回值。* @param rvt* 匹配com.lfy.impl包下的所有类所有方法的执行作为切入点* 声明rvt时指定的类型会限制目标方法必须返回指定类型的值或没有返回值* 此处将rvt的类型声明为Object,意味着对目标方法的返回值不加限制,* 即目标方法可以是void返回类型,也可以是Object的所有子类,即无限制*/@AfterReturning(returning="rvt",pointcut="execution(* com.lfy.impl.*.*(..))")public void log(Object rvt) {System.out.println("AfterReturning获取目标方法返回值: "+rvt);System.out.println("AfterReturning模拟记录日志功能...");}
3》AfterThrowing增强处理
使用@AfterThrowing注解一个切面方法,AfterThrowing用于处理未处理的异常。
/*** * 该注解可以指定pointcut/value,returning这两个常用的属性:<br>* 1>>pointcut/value:用于指定切入点表达式,可以是已有的切入点,也* 可以直接指定表达式。pointcut指定的值会覆盖value指定的值。<br>* 2>>returning:指定一个形参名,用于表示增强处理方法中可定义与此同名* 的形参,该形参可用于访问目标方法抛出的异常。除此之外,在增强处理方法上定义* 的该形参(代表目标方法抛出的异常)指定的类型,将限制目标方法必须抛出该类型* 的异常。* @param ex* 匹配com.lfy.impl包下的所有类所有方法的抛异常作为切入点* 声明ex时指定的类型会限制目标方法必须抛出指定类型的异常* 此处将ex的类型声明为Throwable,意味着对目标方法抛出的异常不加限制。<br>* * @说明:该增强处理能够处理该异常,但不能完全处理该异常,异常还将在目标函数往父级* 传递。catch异常捕获则是完全处理。<br>*/@AfterThrowing(throwing="ex",pointcut="execution(* com.lfy.impl.*.*(..))")public void doRecoveryActions(Throwable ex) {System.out.println("AfterThrowing目标方法中抛出的异常:"+ex);System.out.println("AfterThrowing模拟增强处理对异常的修复业务...");}
4》After增强处理
使用@After注解切面方法
package com.lfy.aspect;import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect;/*** After增强处理* @author lfy* 与AfterReturning的区别:AfterReturning增强处理只有在目标方法成功完成后才会被织入,* After增强处理无论目标方法如何结束(包括成功完成和遇到异常中止),它都会被织入。* After需要处理正常返回和异常返回两种情况。After增强处理需要指定一个value属性,用于指定已* 有的切入点,或者切入点表达式。*/ @Aspect public class AfterAspect {@After("execution(* com.lfy.impl.*.*(..))")public void release() {System.out.println("After模拟方法结束后的释放资源...");} }
5》Around增强处理
使用@Around注解切面方法。Around的功能近似是Before增强处理和AfterReturning增强处理的总和,它既可以在目标方法前织入增强处理,也可以在执行目标方法后织入增强处理。
目标方法作为它的一个回调,不是必须的,也就是增强处理完全可以阻止目标方法的执行。
还可以修改目标方法的入参,或者改变目标方法执行后的返回值。
它不是一个线程安全的增强处理,通常需要保证它在线程安全的环境下执行。
使用时指定的value值可以是一个已有的切入点,也可以是一个切入点表达式。
当定义一个Around增强处理方法时,该方法的第一个参数必须是ProceedingJoinPoint类型(至少包含一个参数),在增强处理方法体内,调用ProceedingJoinPoint参数的proceed()方法才会执行目标方法,proceed()相当于就是目标方法,proceed()方法没有被调用,则目标方法不会被执行。调用proceed()方法还可以传入一个Object[]对象作为参数,相当于给目标方法传递实参。
package com.lfy.aspect;import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect;/*** Around增强处理* @author lfy**/ @Aspect public class AroundAspect {/*** * @return Object* @throws Throwable * */@Around("execution(* com.lfy.impl.*.*(..))")public Object processTx(ProceedingJoinPoint jp) throws Throwable {System.out.println("Around执行目标方法之前,模拟开始事务...");//获取目标方法原始的调用参数Object[] args=jp.getArgs();if(args!=null&&args.length>1) {//修改目标方法调用参数的第一个参数args[0]="[增强的前缀]"+args[0];}//改变后的参数去执行目标方法,并保存目标方法执行后的返回值Object rvt=jp.proceed(args);System.out.println("Around执行目标方法之后,模拟结束事务...");//如果rvt的类型是Integer,将rvt改为它的平方if(rvt!=null&&rvt instanceof Integer) {rvt=(Integer)rvt*(Integer)rvt;}return rvt;} }
传入的参数Object[]数组长度与目标方法所需要参数的个数不相等,或者类型不匹配,都会引发异常。为了能够获取目标方法的参数的个数和类型,需要增强处理方法能够访问目标方法的参数。
6》访问目标方法的参数
访问目标方法的参数,最简单的做法是定义增强处理方法第一个参数定义为JoinPoint类型(ProceedingJoinPoint继承于JoinPoint),当该增强处理方法被调用时,该JoinPoint参数就代表了织入增强处理的连接点,JonPoint包含了如下常用方法:
1>Object[] getArgs():返回执行目标方法的参数。
2>Signature getSignature():返回被增强的方法的相关信息。
3>Object getTarget():返回被织入增强处理的目标对象。
4>Object getThis():返回AOP框架为目标对象生成的代理对象。
举个例子:
FourAdviceGetParamerAspect.java
package com.lfy.aspect;import java.util.Arrays;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut;/*** Around、Before、After、AfterReturning四种增强处理<br>* 访问目标方法最简单的做法是定义增强处理方法时将第一个参数定义为JoinPoint类型,* 当该增强处理方法被调用时,该JoinPoint参数就代表了织入增强处理的连接点。JoinPoint* 提供了如下的常用访问方法:<br>* 1>Objeact[] getArgs():返回目标方法的参数<br>* 2>Signature getSignature():返回目标方法的相关信息<br>* 3>Object getTarget():返回被增强处理的对象<br>* 4>Object getThis():返回AOP框架为目标对象生成的代理对象。<br>* 在这些方法中,只有Around增强处理中可以对目标方法的参数进行修改!<br>* @author lfy** 切入点组合连接符有&&、||、!*/ @Aspect public class FourAdviceGetParamerAspect {@Around("execution(int com.lfy.impl.HelloImpl.fourAdviceGetParamer(..)) || PointcutUtil.myPointcut()")public Object processTx(ProceedingJoinPoint jp) throws Throwable {System.out.println("FourAdviceGetParamerAspect.Around执行目标方法之前,模拟开始事务...");//获取目标方法原始的调用参数Object[] args=jp.getArgs();if(args!=null && args.length>0 && args[0].getClass() == String.class) {//修改目标方法调用参数的第一个参数args[0]="[增强的前缀]"+args[0];}//改变后的参数去执行目标方法,并保存目标方法执行后的返回值Object rvt=jp.proceed(args);System.out.println("FourAdviceGetParamerAspect.Around执行目标方法之后,模拟结束事务...");System.out.println("<---------------->");//如果rvt的类型是Integer,将rvt改为它的平方if(rvt!=null&&rvt instanceof Integer) {rvt=(Integer)rvt*(Integer)rvt;}return rvt;}@Before("execution(int com.lfy.impl.HelloImpl.fourAdviceGetParamer(..)) || PointcutUtil.myPointcut()")public void authority(JoinPoint jp) {System.out.println("FourAdviceGetParamerAspect.Before模拟执行权限检查");//返回被织入增强的目标方法System.out.println("被织入的目标方法是: "+jp.getSignature().getName());System.out.println("被织入的目标方法的参数: "+Arrays.toString(jp.getArgs()));System.out.println("被织入增强处理的目标对象为: "+jp.getTarget());System.out.println("<---------------->");}@After("execution(int com.lfy.impl.HelloImpl.fourAdviceGetParamer(..)) || PointcutUtil.myPointcut()")public void release(JoinPoint jp) {System.out.println("FourAdviceGetParamerAspect.After模拟方法结束后的释放资源...");//返回被织入增强的目标方法System.out.println("被织入的目标方法是: "+jp.getSignature().getName());System.out.println("被织入的目标方法的参数: "+Arrays.toString(jp.getArgs()));System.out.println("被织入增强处理的目标对象为: "+jp.getTarget());System.out.println("<---------------->");}@AfterReturning(returning="rvt",pointcut="execution(int com.lfy.impl.HelloImpl.fourAdviceGetParamer(..)) || PointcutUtil.myPointcut()")public void log(JoinPoint jp,Object rvt) {System.out.println("FourAdviceGetParamerAspect.AfterReturning获取目标方法返回值: "+rvt);System.out.println("FourAdviceGetParamerAspect.AfterReturning模拟记录日志功能...");//返回被织入增强的目标方法System.out.println("被织入的目标方法是: "+jp.getSignature().getName());System.out.println("被织入的目标方法的参数: "+Arrays.toString(jp.getArgs()));System.out.println("被织入增强处理的目标对象为: "+jp.getTarget());System.out.println("<---------------->");} }
PointcutUtil.java
package com.lfy.aspect;import org.aspectj.lang.annotation.Pointcut;/*** 切入点组合连接符有&&、||、!* @author lfy**/ public class PointcutUtil {//使用@Pointcut注解定义切入点,public控制着切入点的访问权限@Pointcut("execution(int com.lfy.impl.HelloImpl.fourAdviceGetParamer(..))")public void myPointcut() {} }
beans.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 --> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"><!-- 指定自动搜索bean组件、自动搜索切面类 --><context:component-scan base-package="com.lfy.aspect,com.lfy.impl"><context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/></context:component-scan><!-- 或者不打算使用spring的xml schema配置方式,则应该在spring配置文件中增加如下片段来启动@AspectJ的支持 <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>为了在spring应用中启动@AspectJ的支持,还需要在应用的类加载路径下增加两个AspectJ库:aspectjweaver.jar和aspectjrt.jar,除此之外,spring AOP还依赖aopalliance.jar--><!-- 启动@AspectJ支持 --><aop:aspectj-autoproxy/><!-- 完全不打算使用spring的xml schema配置方式使用spring AOP,即bean的注册也使用注解的形式。应该加入如下代码 ,AnnotationAwareAspectJAutoProxyCreator是一个bean后处理器,该bean后处理器将会为容器中的所有bean生成AOP代理--><bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/> </beans>
HelloImpl.java
package com.lfy.impl;import org.springframework.stereotype.Component;import com.lfy.bean.Hello;/*** 被增强的目标类* @author lfy**/ @Component("hello") public class HelloImpl implements Hello {@Overridepublic void foo() {System.out.println("执行Hello组件的foo()方法");}@Overridepublic void addUser(String name, String pass) {System.out.println("执行Hello组件的addUser()添加用户: "+name+",pass为"+pass);}@Overridepublic int addGroup(String groupName, int groupMemberNumber) {System.out.println("执行Hello组件的addGroup()添加群组: "+groupName);if(groupMemberNumber<0||groupMemberNumber>100) {throw new IllegalArgumentException("群组成员数在0~100之间");}return 0;}@Overridepublic int fourAdviceGetParamer(String param) {System.out.println("执行Hello组件的fourAdviceGetParamer()方法,param:"+param);return 5;}}
SpringAOPTest.java
package com.lfy.main;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import com.lfy.bean.Hello;/*** 1、基于注解的“零配置”方式,演示获取切入点信息* @author lfy* 未登记的知识点:* 1>指定增强处理的优先级,@Order注解及Orderd接口* 2>切入点指示符*/ public class SpringAOPTest {public static void main(String[] args) {ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");Hello hello=ctx.getBean("hello", Hello.class);hello.addUser("孙悟空", "7788");System.out.println("****************\n");System.out.println("fourAdviceGetParamer默认只返回5,经过平方后:"+hello.fourAdviceGetParamer("唐僧"));}}
运行结果:各方法内成功的获取到了切入点相关信息。Around增强处理修改了目标方法的入参、返回值,其实也只有Around增强可以修改并生效(影响)到目标方法。
7》如果只需要访问目标方法的参数
可以在程序中用args切入点表达式来绑定目标方法的参数。如果一个args表达式中指定了一个或多个参数,则该切入点将只匹配具有对应形参的方法(包括参数个数以及参数类型),且目标方法的参数值将被传入增强处理方法。
@AfterReturning(returning="rvt",pointcut="execution(* com.lfy.impl.*.*(..)) && args(arg0,arg1)") public void log(Object rvt,String arg0,String arg1) {... }
上面的切入点表达式增加了&&args(arg0,arg1)部分,且log()方法还指定了它们是String类型,则该增强处理只匹配参数是两个个且均为String类型的目标方法。
如果表达式args部分为&&args(name,age, .. ),注意最后面是两点,这说明最少匹配两个参数(包括增强处理指定的类型),第三个参数可以是0到无限多个,且类型由增强处理决定,如:
@AfterReturning(returning="rvt",pointcut="execution(* com.lfy.impl.*.*(..)) && args(arg0,arg1,..)") public void log(Object rvt,String arg0,String arg1,Date date) {... }
转载于:https://www.cnblogs.com/ZeroMZ/p/11335839.html
spring-第十七篇之spring AOP基于注解的零配置方式相关推荐
- java @around,Spring AOP基于注解的Around通知
是一种建议类型,可确保方法执行前后的通知可以运行. 以下是通知的语法: 语法 @Pointcut("execution(* com.yiibai.Student.getAge(..))&qu ...
- Spring Boot(十七):使用Spring Boot上传文件
Spring Boot(十七):使用Spring Boot上传文件 环境:Spring Boot最新版本1.5.9.jdk使用1.8.tomcat8.0 一.pom包配置 <parent> ...
- spring 基于注解的控制器配置
http://ttaale.iteye.com/blog/787586 spring 基于注解的控制器配置 博客分类: spring SpringBeanServletMVCWeb 13.12. 基于 ...
- java day58【 案例:使用 spring 的 IoC 的实现账户的 CRUD 、 基于注解的 IOC 配置 、 Spring 整合 Junit[掌握] 】...
第1章 案例:使用 spring 的 IoC 的实现账户的 CRUD 1.1 需求和技术要求 1.1.1 需求 1.1.2 技术要求 1.2 环境搭建 1.2.1 拷贝 jar 包 1.2.2 创建数 ...
- 基于注解的 IOC 配置
基于注解的 IOC 配置 学习基于注解的 IoC 配置,大家脑海里首先得有一个认知,即注解配置和 xml 配置要实现的功能都是一样 的,都是要降低程序间的耦合.只是配置的形式不一样. 关于实际的开发中 ...
- 缓存初解(五)---SpringMVC基于注解的缓存配置--web应用实例
之前为大家介绍了如何使用spring注解来进行缓存配置 (EHCache 和 OSCache)的简单的例子,详见 Spring基于注解的缓存配置--EHCache AND OSCache 现在介绍一下 ...
- IoC容器9——基于注解的容器配置
2019独角兽企业重金招聘Python工程师标准>>> 基于注解的容器配置 注解比XML更适合配置Spring吗? 引入基于注解的配置提出了这种方法是否比XML更好的问题.简短的回答 ...
- 基于注解的 IOC 配置——创建对象(Component、Controller、Service、Repository)注入数据(Autowired、Qualifier、Resource、Value)
基于注解的 IOC 配置 注解配置和 xml 配置要实现的功能都是一样的,都是要降低程序间的耦合.只是配置的形式不一样. XML的配置: 用于创建对象的 用于注入数据的 用于改变作用范围的 生命周期相 ...
- Spring学习(20)--- Schema-based AOP(基于配置的AOP实现) -- 配置切入点pointcut
pointcut(切断点)表达式: execution(public * *(..)) execution(* set*(..)) execution(* com.xyz.service.Accoun ...
- spring ioc的包的扫描(基于注解)
一.包扫描初始步骤源码分析 AnnotationConfigApplicationContext aac =new AnnotationConfigApplicationContext("c ...
最新文章
- python 图表_Python入门学习系列——使用Python调用Web API实现图表统计
- Perl5的OOP学习笔记
- 桂林哪些职校可以学计算机,桂林市有几个中等职业学校
- 人工智能之神经网络要进入的下一个阶段-演绎推理
- swing的gui是通过何种模式进行事件响应与监听_【Vert.x准备篇2】C10K问题与Reactor模式...
- 正则表达式练习 Regex Golf
- WPF Calendar 日历控件 样式自定义
- 机器学习Sklearn实战——其他线性回归模型、逻辑回归
- 浅谈输入输出”重定向“——基于Linux系统
- 干货 | 深度学习名词表:57个专业术语加相关资料解析(附论文)
- android 定位 广播,android - 如何触发广播接收器在GPS开启/关闭? - SO中文参考 - www.soinside.com...
- java web服务_将Java服务公开为Web服务
- 输入输出Fibonacci数
- 实用的 BOM 属性对象方法
- 【BZOJ-14492895】球队收益球队预算 最小费用最大流
- 如何将一个java程序变成exe_如何将一个java程序转换为.exe文件?
- 基于人脸识别的课堂签到管理系统(二)---摄像头显示
- VUE Right-hand side of ‘instanceof’ is not an object 解决方案
- 图像分割(二)--Graph Cuts
- 如何判断Intent有没有对应的Activity去处理?
热门文章
- ProGuard混淆时保留注释(@类内容)
- Looking for pthread_create - not found
- 文件比较,忽略目录引起编译出错
- 百度网盘不能上传超过百兆的文件?
- 泰山游记:为何爬山后大腿前部很酸?
- 解决办法:error LNK2005: void * __cdecl operator new(unsigned int) 已经在 LIBCMTD.lib(new.obj) 中定义
- 用char*作为map的key
- 管理感悟:你说负责,关键在于怎样负责?
- 管理感悟:轮值不是记流水账
- INSTALL_FAILED_TEST_ONLY的解决办法