springAOPjava
IOC叫控制反转,对象的建立由外部框架来实现,控制权交给了外部容器,控制发生了反转,也叫依赖注入,程序中须要对象,则依赖外部框架把对象进行注入。IOC是一个容器,对象被建立以后都存储在这个容器中,对象默认是单例模式,能够经过scope这个属性来改变。对象的配置能够在配置文件中处理,也能够运用注解的方式来建立对象,程序经过ApplicationContext.getBean()这个方法来获取对象,也能够经过注解@Autowired或@Resource(name="stu12")自动注入。若是是经过注解的方式来自动建立Bean,则配置文件要启动注解并扫描相关的包,类前还须要添加相关的注解: @Service,@Component,@Controller,@Repository。spring
面向切面编程,对于程序内部进行横切关注,把公共的代码抽取出来,造成切面,再经过链接点去监听指定方法的执行状况,在方法执行过程当中把切面织入到被监听的方法中去。方法被动的被执行某些功能代码。express
Aspect(切面):指横切性关注点的抽象即为切面,它与类类似,只是二者的关注点不同,类是对物体特征的抽象,而切面是横切性关注点的抽象.编程
joinpoint(链接点):所谓链接点是指那些被拦截到的点。在spring中,这些点指的是方法,由于spring只支持方法类型的链接点,实际上joinpoint还能够是field或类构造器)app
Pointcut(切入点):所谓切入点是指咱们要对那些joinpoint进行拦截的定义.框架
Advice(通知):所谓通知是指拦截到joinpoint以后所要作的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知spa
Target(目标对象):代理的目标对象代理
Weave(织入):指将aspects应用到target对象并致使proxy对象建立的过程称为织入.component
Introduction(引入):在不修改类代码的前提下, Introduction能够在运行期为类动态地添加一些方法或Field.xml
aopalliance-1.0.0.jar aspectjweaver-1.6.8.jar commons-logging-1.1.1.jar spring-aop-4.3.10.RELEASE.jar spring-aspects-4.3.10.RELEASE.jar spring-beans-4.3.10.RELEASE.jar spring-context-4.3.10.RELEASE.jar spring-core-4.3.10.RELEASE.jar spring-expression-4.3.10.RELEASE.jar |
@Component //扫描到IOC容器中去 @Aspect //表示这个类是一个切面类 public class LogInfo { /* execution(public springAOP0305.Calc.*(int, int))切面表达式,指定要监听的方法 * springAOP0305.Calc.* 是一个通配符,任何方法都行,int,int是方法的参数,必须是两个int型才监听。 * 能够改为.. 表示任意类型,任意数量的参数都行 */ //前置通知,在监听的方法执行前执行.. @Before("execution(* springAOP0305.*.*(..))") public void before() { System.out.println("方法开始执行.......... "); }
//后置通知,在方法正确执行完毕,返回结果以前执行。 @After("execution(* springAOP0305.*.*(..))") public void after() { System.out.println("方法执行结束..."); } } |
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 "> <!-- 启用注解配置,--> <context:annotation-config/> <!-- 扫描包中的类,把有注解的类自动建立出对象,存储在IOC容器中 --> <context:component-scan base-package="springAOP0305"/> <!-- 启动AOP的代理 --> <aop:aspectj-autoproxy proxy-target-class="true"/> </beans> |
public static void main(String[] args) { ApplicationContext cxt = new ClassPathXmlApplicationContext("config/applicationcontext.xml"); Calc c = cxt.getBean(Calc.class); int result = c.add(100, 50, 20); System.out.println("计算结果是:"+result); } |
|
通知:
/* * execution(public springAOP0305.Calc.*(int, int))切面表达式,指定要监听的方法 * springAOP0305.Calc.* 是一个通配符,任何方法都行,int,int是方法的参数,必须是两个int型才监听。 能够改为.. * 表示任意类型,任意数量的参数都行 */ // 前置通知,在监听的方法执行前执行.. @Before("execution(* springAOP0305.*.*(..))") public void before(JoinPoint jp) { // JoinPoint 是一个链接点对象,封装了方法名称及参数,jp.getSignature().getName()方法名称 String name = jp.getSignature().getName(); Object[] args = jp.getArgs(); // 取链接点的参数列表 System.out.println(name + "方法: 开始执行,参数是:" + Arrays.toString(args)); }
// 后置通知,在方法正确执行完毕,返回结果以前执行,不能获取方法的返回结果。 @After("execution(* springAOP0305.*.*(..))") public void after(JoinPoint jp) { // JoinPoint 是一个链接点对象,封装了方法名称及参数,jp.getSignature().getName()方法名称 String name = jp.getSignature().getName(); Object[] args = jp.getArgs(); // 取链接点的参数列表 System.out.println(name + "方法: 执行结束了,参数是:" + Arrays.toString(args)); }
/* * 返回通知,也叫最终通知,在方法返回结果时执行,此时能够获取到方法返回的结果 * value表示切面表达式, * returning:表示方法返回的结果封装的参数名称 */ @AfterReturning(value = "execution(* springAOP0305.*.*(..))", returning = "result") public void afterReturn(JoinPoint jp, Object result) { // JoinPoint 是一个链接点对象,封装了方法名称及参数,jp.getSignature().getName()方法名称 String name = jp.getSignature().getName(); Object[] args = jp.getArgs(); // 取链接点的参数列表 System.out.println(name + "方法: 正确返回结果,参数是:" + Arrays.toString(args)+",计算结果是:"+result); } //异常通知,也叫例外通知,在方法执行中出现异常才执行,不然不执行,若是有异常,则返回通知不会执行 @AfterThrowing("execution(* springAOP0305.*.*(..))") public void afterThrow() { System.out.println("发生错误.."); } |
当有多个切面的时候,能够给切面执行顺序进行设置,在切面类前添加注解@Order(value=1), 值越小,优先级越高。
@Aspect @Component @Order(value=1) //顺序设置,值小的优先级高 public class TimeInfo { @Before("execution(* springAOP0305.*.*(..))") public void befor() { System.out.println("时间开始记录.."); } } |
在开发中大部分仍是采用注解的方式来进行配置,事务管理机制,采用的就是注解配置,简单。
<!-- 切面类的对象 --> <bean id="logInfo" class="springAOP0305.LogInfo"/> <bean id="timeInfo" class="springAOP0305.TimeInfo"/>
<!-- AOP配置 --> <aop:config> <!-- 切入点:切点表达式, --> <aop:pointcut expression="execution(* springAOP0305.*.*(..))" id="pcut"/> <!-- 切面及通知的配置 order:切面织入的顺序 --> <aop:aspect ref="timeInfo" order="1"> <aop:before method="befor" pointcut-ref="pcut"/> </aop:aspect> <aop:aspect ref="logInfo" order="2"> <aop:before method="before" pointcut-ref="pcut"/> <aop:after method="after" pointcut-ref="pcut"/> </aop:aspect> </aop:config> |
expression-匹配方法执行的链接点,是Spring最主要的切入点
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
除了返回类型模式(),名字模式和参数模式之外,其他的都是可选的,*为任意通配符
expression=“execution(* cn.itcast.service..*.*(..))”表示做用在cn.itcast.service包及子包下全部的类的全部方法上
expression=“execution(* cn.itcast.service..*.*(java.lang.String,..))”表示做用在cn.itcast.service包及子包下全部的类的第一个参数为String类型的方法上
expression=“execution(java.lang.String cn.itcast.service..*.*(..))” 表示做用在cn.itcast.service包及子包下全部的类的返回值类型为String的方法上
expression=“execution(!java.lang.String cn.itcast.service..*.*(..))” 表示做用在cn.itcast.service包及子包下全部的类的返回值类型不是String的全部方法上
expression=“execution(* set**(..))” 表示做用在任意以set开始的方法上
within-限定匹配特定类型的链接点
expression=“winthin(cn.itcast.*)” 表示做用在cn.itcast包及子包下的全部链接点