【0】README
1)本文部分文字描述转自:“Spring In Action(中/英文版)”,旨在review  “spring(4)面向切面的Spring(AOP)” 的相关知识;
2)在软件开发中,散布于应用中多处的功能被称为横切关注点。通常来讲,这些横切关注点从概念上是与应用的业务逻辑相分离的(但是往往会直接嵌入到应用的业务逻辑中)。把这些横切关注点与业务逻辑相分离正是面向切面编程(AOP)所要解决的问题;(干货——引入横切关注点及其所要解决的问题)
3)要知道,DI有助于应用对象之间的解耦,而AOP 可以实现横切关注点与它们所影响的对象之间的解耦;(干货——DI 和 AOP 的作用)
4)本文内容概览:
4.1)暂时了Spring对切面的支持,包括如何把普通类声明为一个切面和如何使用注解创建切面;
4.2)除此之外,还可以看到 AspectJ——另一种流行的AOP实现——如何补充Spring AOP的功能;(干货——引入AspectJ框架)
【1】什么是面向切面编程
1)problem+solution:
1.1)problem:如果要重用通用功能的话,最常见的技术是继承或委托。但是,如果在整个应用中都使用相同的基类,继承往往会导致一个脆弱的对象体系;
1.2)solution:切面提供了取代继承和委托的另一种可选方案;
2)切面:横切关注点可以被模块化为特殊的类,这些类被称为切面;这样做有两个好处(merits)(干货——切面的定义)
m1)现在每个关注点都集中于一个地方,而不是分散到多处;
m2)服务模块更加简洁了,因为它们只包含主要关注点的代码,而次要关注点的代码被转移到切面中了;
【1.1】定义AOP术语
1)描述切面的术语有:通知,切点,连接点;
1.1)通知(Advice):切面的工作被称为通知;通知定义了切面是什么以及何时使用;(5中类型的通知:前置通知,后置通知,返回通知,异常通知,环绕通知)
1.2)连接点(Join point):是在应用执行过程中能够插入切面的一个点;
1.3)切点(Pointcut):如果说通知定义了切面是什么和何时执行的话,那么切点就定义了 何处(在何处执行),切点的定义会匹配通知所要织入的一个或多个连接点;
1.4)切面(Aspect):切面是通知和切点的结合。通知和切点共同定义了切面的全部内容——它是什么?
1.5)引入(Introduction):引入允许我们向现有的类添加新方法或属性;
1.6)织入(Weaving):织入是吧切面应用到目标对象并创建新的代理对象的过程;切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点可以进行织入:
peroid1)编译期:切面在目标类编译时被织入;AspectJ的织入编译器就是以这种方式织入切面的;
peroid2)类加载期:切面在目标类加载到 jvm 时 被织入;这种方式需要特殊的类加载器(ClassLoader),它可以在目标类被引入应用之前增强该目标类的字节码;AspectJ 5 的加载时织入(load-time weaving,LTW)就支持以这种方式织入切面;
period3)运行期:切面在应用运行的某个时刻被织入;一般case下,在织入切面时,AOP 容器会为目标对象动态地创建一个代理对象。Spring AOP 就是以这种方式织入切面的;
【1.2】Spring对AOP 的支持
1)Spring 和 AspectJ 之间有大量的协作,而且Spring 对 AOP 的支持在很多方面借鉴了 AspectJ 项目;
2)spring 提供了4中类型的 AOP支持:
type1)基于代理的经典 spring AOP;
type2)纯 POJO 切面;
type3)@AspectJ 注解驱动的切面;
type4)注入式 AspectJ 切面(适用于spring 各种version);
Attention)
A1)前三种都是 spring aop 实现的变体,spring aop 构建在动态代理基础之上:因此,spring 对 aop的支持局限于方法拦截;(干货——spring 对 aop的支持局限于方法拦截)
A2)spring 借鉴了AspectJ 的切面,以提供注解驱动的AOP。本质上,它依然是 spring 基于代理的aop,但是编程模型几乎与编写成熟的 AspectJ 注解切面完全一致。这种aop 风格的好处在于能够不使用XML 来完成功能;
3)spring 在运行时通知对象:通过在代理类中包裹切面,spring 在运行期吧切面织入到 spring管理的bean中。 如下图所示。代理类封装了目标类,并拦截被通知方法的调用,再把调用转发给真正的目标bean。当代理拦截到方法调用时,在调用目标bean 方法之前,会执行切面逻辑;
4)spring 只支持方法级别的连接点: 通过使用各种aop 方案可以支持多种连接点模型;
4.1)因为spring基于动态代理,所以spring 只支持方法连接点。这与一些其他的AOP 框架是不同的,例如 AspectJ 和 JBoss,除了方法切点外,它们还提供了字段和构造器接入点;(干货——因为spring基于动态代理,所以spring 只支持方法连接点)
4.2)方法拦截可以满足绝大部分的需求;如果需要方法拦截之外的连接点拦截功能,可以利用 Aspect 来补充 spring aop 的功能;
【2】通过切点来选择连接点
1)关于spring aop 的AspectJ 切点,最重要的一点是:spring仅仅支持AspectJ 切点指示器的一个子集;
2)review:spring是基于代理的,而某些切点表达式是与基于代理的aop 无关的,下表列出了 spring aop 所支持的 AspectJ 切点指示器;
Attention)只有 execution指示器: 是实际执行匹配的,而其他的指示器都是用来限制匹配的;它是最主要使用的指示器;
【2.1】编写切点
1)需要有个主题来定义切面的切点:
public interface Performance {public void perform();
}

2)表达式execution(* concert.Performance.perform(..)):这个表达式能够设置当 perform()方法执行时触发通知的调用;

3)假设我们需要匹配的切点仅匹配 concert 包,在此case下,可以使用  within() 指示器来限制匹配, 如下图所示;
【2.2】在切点中选择bean
1)bean()指示器:spring 引入了新的bean()指示器,它允许我们在切点表达式中使用 bean  的ID 来标识 bean。(干货——引入指示器的概念)
2)看个荔枝:
execution(* concert.Performance.perform())  and bean('jaychou') :我们希望在执行Performance.perform方法时应用通知,但限定bean的ID为 jaychou;
execution(* concert.Performance.perform())  and !bean('jaychou'): 我们希望在执行Performance.perform方法时应用通知,但限定bean的ID不为 jaychou;
【3】使用注解创建切面
1)intro:使用注解来创建切面是 AspectJ 5 所引入 的关键特性;
【3.1】定义切面
1)看个荔枝:将考生定义为一个切面;
@Aspect
public class Examinee { // 考生@Before("execution(** com.spring.chapter4.CollegeEntraceExamination.chineseExamination(..))")public void checkIdentity() { // 身份审查System.out.println("please show us your admission ticket.");}@Before("execution(** com.spring.chapter4.CollegeEntraceExamination.chineseExamination(..))")public void checkSecurity() { // 安检System.out.println("please accept electronic equipment inspection.");}@AfterReturning("execution(** com.spring.chapter4.CollegeEntraceExamination.chineseExamination(..))")public void handinPaper() { // 交卷System.out.println("please hand in an examination paper.");}@AfterThrowing("execution(** com.spring.chapter4.CollegeEntraceExamination.chineseExamination(..))")public void cancelQualification() { // 取消考试资格System.out.println("cancel the exam qualification");}
}
对以上代码的分析(Analysis):
A1)spring使用了 AspectJ 注解来声明通知方法, 如下表所示:
A2)上面的注解都给定了一个切点表达式作为它的值,且这4个切点表达式都是相同的,其实它们可以设置成为不同的切点表达式;

3)problem+solution:
3.1)problem:相同的切点表达式出现了四遍,这可是不光彩的事情;
3.2)solution:引入了 @PointCut注解, 该注解能够在一个 @AspectJ 切面内定义可重用个切点;
@Aspect
public class ExamineeVersion2 {@Pointcut("execution(** com.spring.chapter4.CollegeEntraceExamination.chineseExamination(..))")public void chineseExamination(){}@Before("chineseExamination()")public void checkIdentity() { // 身份审查System.out.println("please show us your admission ticket.");}@Before("chineseExamination()")public void checkSecurity() { // 安检System.out.println("please accept electronic equipment inspection.");}@AfterReturning("chineseExamination()")public void handinPaper() { // 交卷System.out.println("please hand in an examination paper.");}@AfterThrowing("chineseExamination()")public void cancelQualification() { // 取消考试资格System.out.println("cancel the exam qualification");}
}

对以上代码的分析(Analysis):
A1)在 Examinee中,chineseExamination()方法使用了 @Pointcut 注解,为@Pointcut注解设置的值是一个切点表达式;
A2)实际上扩展了切点表达式语言,这就可以在 任何的切点表达式中使用 chineseExamination()方法了;
4)problem+solution:
4.1)problem:如果仅仅是以上代码的话,即便使用了AspectJ 注解,但它也不会被视为切面,这些注解不会解析,也不会创建将其转换为切面的代理;
4.2)solution:如果使用JavaConfig的话,可以在配置类的类级别上通过使用 @EnableAspectJAutoProxy 注解启用自动代理功能;(干货——@EnableAspectJAutoProxy 注解的作用)
@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class ExaminationConfig {@Beanpublic Examinee getExaminee() {return new Examinee("xiaotang");}
}

4.3)如果使用XML配置类装配bean的话,使用 spring aop命名空间中的 <aop:aspectj-autoproxy> 元素:

Attention) 
A1)不管使用JavaConfig 还是 XML配置来装配:AspectJ 自动代理都会为使用 @AspectJ 注解的bean创建一个代理,这个代理会围绕着所有该切面的切点所匹配的bean;
A2)在这种case下,将会为 Examination bean创建一个代理,Examinee类中的通知方法将会在 chineseExamination() 方法调用前后执行;
A3)spring的 AspectJ 自动代理仅仅是使用 @AspectJ 作为创建切面的指导,切面依然是基于代理的;本质上,它依然是 spring基于代理的切面;
【3.2】创建环绕通知
1)intro:环绕通知是最强大的通知类型。它能够让你所编写的逻辑将被通知的目标方法完全包装起来。实际上就想是在一个通知方法中通知编写前置通知和后置通知;
2)看个荔枝:重写 Eaxminee 切面;
// 考生(就是一个切面)
@Aspect
public class ExamineeVersion3 {@Pointcut("execution(** com.spring.chapter4.CollegeEntraceExamination.chineseExamination(..))")public void chineseExamination() {}@Around("chineseExamination()")public void doChineseExamination(ProceedingJoinPoint jp) {try {System.out.println("please show us your admission ticket.");System.out.println("please accept electronic equipment inspection.");jp.proceed();System.out.println("please hand in an examination paper.");} catch (Throwable e) {System.out.println("cancel the exam qualification");}}
}
对以上代码的分析(Analysis):
A1)@Around注解表明 doChineseExamination() 方法会作为 chineseExamination() 切点的环绕通知;(干货——@Around注解的作用)
A2)别忘记调用 ProceedingJoinPoint.proceed()方法,如果不调用这个方法的话,那么你的通知实际上会阻塞对被通知方法的调用;
A3)当然,你可以不调用ProceedingJoinPoint.proceed()方法,你也可以在通知中对它进行多次调用;
【3.3】处理通知中的参数
1)除了环绕通知,我们编写的其他通知不需要关注传递给被通知方法的任意参数;
2)如果切面所通知的方法确实有参数该怎么办?切面能访问和使用传递给被通知方法的参数吗?
3)看个荔枝:
对以上代码的分析(Analysis):
A1)这里的不同点在于切点还声明了要提供给通知方法的参数;
A2)关注 args(trackNumber))限定符:它表明传递给 playTrack()方法的int类型参数也会传递到通知里面去,参数的名称 trackNumber 也与切点方法签名中的参数相匹配;
A3)这个参数会传递到通知方法中:该方法是通过 @Before 注解和命名切点 trackPlayed(trackNumber)定义的。切点定义中的参数与切点方法中的参数名称是一样的,这样就完成了从命名切点到通知方法的参数转移;
@Aspect
public class ExamineeArgs {private String name;public ExamineeArgs(String name) {this.name = name;}@Pointcut("execution(* com.spring.chapter4.CollegeEntraceExamination.getExamineeNumber(int)) "+ "&& args(examSiteCode)")public void myGetExamineeNumber(int examSiteCode) {}@Before("myGetExamineeNumber(examSiteCode)")public void checkIdentity(int examSiteCode) { // 身份审查System.out.println("@Before: your exam site code is " + examSiteCode);}
}

【3.4】通过注解引入新功能
1)intro:切面能够为现有的方法增加新功能,利用aop概念,切面与可以为 spring bean 添加新方法;

2)当引入接口的方法被调用时,代理会把此调用委托给实现了新接口的某个其他对象。实际上,一个bean的实现被拆分到了多个类中;(干货——一个spring bean的实现被拆分到了多个类中)

3)借助于aop 的引入功能,可以不必在设计上妥协或侵入性地改变现有的实现。为了实现该功能,我们要创建一个新切面;
@Aspect
public class ExamineeArgs {private String name;public ExamineeArgs(String name) {this.name = name;}@Pointcut("execution(* com.spring.chapter4.CollegeEntraceExamination.getExamineeNumber(int)) "+ "&& args(examSiteCode)")public void myGetExamineeNumber(int examSiteCode) {    }@Before("myGetExamineeNumber(examSiteCode)")public void checkIdentity(int examSiteCode) { // 身份审查System.out.println("@Before: your exam site code is " + examSiteCode);}
}// 高考
public class CollegeEntraceExamination {public CollegeEntraceExamination() { }public void chineseExamination() {System.out.println("chinese examination is underway.");}public int getExamineeNumber(int examSiteCode) {return 1000;}
}
//---------------------------------------我是分割线.
@Aspect
public class AdditionExaminationIntroducer{@DeclareParents(value="com.spring.chapter4.CollegeEntraceExamination.chineseExamination+",defaultImpl=AdditionExaminationImpl.class)public static AddtionExamination addtionExamination;
}
public interface AddtionExamination {void doAddtionalExamination();
}
public class AdditionExaminationImpl implements AddtionExamination{@Overridepublic void doAddtionalExamination() {System.out.println("do additional questions as possible as you can.");}
}
对以上代码的分析(Analysis):
A1)这个切面与以往切面不同的是:它并没有前置,后置等通知,而是通过 @DeclareParents注解将 AddtionExamination  接口引入到 CollegeEntraceExamination bean中;
A2)@DeclareParents注解由3个部分组成:(干货——@DeclareParents注解的作用)
part1)value属性:指定了哪种类型的bean 要引入该接口;
part2)defaultImpl:指定了为引入功能提供实现的类;
part3)@DeclareParents注解所标注的静态属性:指明了要引入的接口;
A3)和其它切面一样,需要在spring 应用中将 AdditionExaminationIntroducer 声明为 一个 bean;
<bean class="com.spring.chapter4.AdditionExaminationIntroducer" />

spring 的自动代理机制将会获取到它的声明,但 spring 发现一个bean使用 @Aspect注解时,spring就会创建一个代理,然后将调用委托给被代理bean 或被引入的实现,这取决于调用的方法属于被代理的bean 还是属于被引入的接口;(干货——这解释了为什么一个spring bean的实现被拆分到了多个类中的问题)

对上图的分析(Analysis):我们看到,即使CollegeEntraceExamination 并没有实现 AddtionExamination接口,但是通过创建新切面为前者添加了新方法,CollegeEntraceExamination 就可以调用了doAddtionalExamination()方法了;
4)面向注解的切面声明有一个明显的劣势:你必须能够为通知类添加注解。为了做到这一点,必须要有源码;如果没有源码,或不想将 AspectJ 注解放到你的代码中,可以使用 spring XML 配置文件中声明切面;(干货——面向注解的切面声明有一个明显的劣势)

【4】在XML 中声明切面
1)之前有这样一个rule:基于注解的bean装配要优于基于JavaConfig 的装配,基于JavaConfig的装配 要优于基于XML的配置装配;
2)但是,如果需要声明切面,但又不能为通知类添加注解的时候,那么就必须转向XML 配置了;
3)spring 的aop 配置元素能够以非侵入性的方式声明切面
【4.1】声明前置和后置通知
1)通过XML 将无注解的 Examinee 声明为切面
<aop:config><aop:aspect ref="examinee"><aop:beforepointcut="execution(** com.spring.chapter4.CollegeEntraceExamination.chineseExamination(..))"method="checkIdentity"/><aop:beforepointcut="execution(** com.spring.chapter4.CollegeEntraceExamination.chineseExamination(..))"method="checkIdentity"/><aop:after-returningpointcut="execution(** com.spring.chapter4.CollegeEntraceExamination.chineseExamination(..))"method="handinPaper"/><aop:after-throwingpointcut="execution(** com.spring.chapter4.CollegeEntraceExamination.chineseExamination(..))"method="cancelQualification"/></aop:aspect>
</aop:config>
2)使用<aop:pointcut> 定义命名切点
<aop:config><aop:aspect ref="examinee"><aop:pointcutid="chineseExamination"expression="execution(** com.spring.chapter4.CollegeEntraceExamination.chineseExamination(..))" /><aop:beforepointcut-ref="chineseExamination"method="checkIdentity"/><aop:beforepointcut-ref="chineseExamination"method="checkIdentity"/><aop:after-returningpointcut-ref="chineseExamination"method="handinPaper"/><aop:after-throwingpointcut-ref="chineseExamination"method="cancelQualification"/></aop:aspect>
</aop:config>
图片t18

Attention)spring4-config.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"  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-3.0.xsd "><aop:aspectj-autoproxy /><aop:config><aop:aspect ref="examineeXML"><aop:pointcut id="chineseExamination"expression="execution(** com.spring.chapter4.CollegeEntraceExamination.chineseExamination(..))" /><aop:before pointcut-ref="chineseExamination" method="checkIdentity" /><aop:before pointcut-ref="chineseExamination" method="checkSecurity" /><aop:after-returning pointcut-ref="chineseExamination" method="handinPaper" /><aop:after-throwing pointcut-ref="chineseExamination" method="cancelQualification" /></aop:aspect></aop:config>
</beans>
【4.2】在XML配置元素中声明环绕通知
step1)attendChineseExamination()方法提供了aop环绕通知;
// 考生(就是一个切面)
public class ExamineeAroundXML {private String name;public ExamineeAroundXML(String name) {this.name = name;}public void attendChineseExamination(ProceedingJoinPoint jp) {try {System.out.println("AroundXML@Before: please show us your admission ticket.");System.out.println("AroundXML@Before: please accept electronic equipment inspection.");jp.proceed();System.out.println("AroundXML@AfterReturn: please hand in an examination paper.");} catch (Throwable e) {System.out.println("AroundXML@AfterThrowing: cancel the exam qualification");}}
}
step2)在XML 中使用 <aop:around>元素声明环绕通知
<aop:config><aop:aspect ref="audience"><aop:pointcutid="chineseExamination"expression="execution(** com.spring.chapter4.CollegeEntraceExamination.chineseExamination(..))" /><aop:aroundpointcut-ref="chineseExamination"method="attendChineseExamination"/></aop:aspect>
</aop:config>
图片t19
【4.3】 为通知传递参数(在XML中将ExamineeXMLArgs 配置为参数化的切面 )
图片t20
@Configuration
@ImportResource("classpath:com/spring/chapter4/spring4-args-config.xml")
public class ExaminationConfig {@Beanpublic CollegeEntraceExamination getExamination() {return new CollegeEntraceExamination();}@Bean(name="examineeXMLArgs")public ExamineeXMLArgs getExamineeXMLArgs() {return new ExamineeXMLArgs("xiaotang");}
}
spring4-args-config.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"  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-3.0.xsd "><aop:aspectj-autoproxy /><aop:config><aop:aspect ref="examineeXMLArgs"><aop:pointcut id="getExamineeNumber"expression="execution(* com.spring.chapter4.CollegeEntraceExamination.getExamineeNumber(int))and args(examSiteCode)" /><aop:before pointcut-ref="getExamineeNumber" method="checkIdentity"/></aop:aspect></aop:config>
</beans>

【4.4】通过XML为切面引入新功能

图片(t21)
@Configuration
@ImportResource("classpath:com/spring/chapter4/spring4-args-intro-config.xml")
public class ExaminationConfig {@Beanpublic CollegeEntraceExamination getExamination() {return new CollegeEntraceExamination();}@Bean(name="examineeXMLArgs")public ExamineeXMLArgs getExamineeXMLArgs() {return new ExamineeXMLArgs("xiaotang");}
}
spring4-args-intro-config.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"  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-3.0.xsd "><aop:aspectj-autoproxy /><aop:config><aop:aspect ref="examineeXMLArgs"><aop:pointcut id="getExamineeNumber"expression="execution(* com.spring.chapter4.CollegeEntraceExamination.getExamineeNumber(int))and args(examSiteCode)" /><aop:before pointcut-ref="getExamineeNumber" method="checkIdentity"/></aop:aspect><aop:aspect><aop:declare-parents types-matching="com.spring.chapter4.CollegeEntraceExamination+" implement-interface="com.spring.chapter4.AddtionExamination" default-impl="com.spring.chapter4.AdditionExaminationImpl"<!-- delegate-ref="additionExaminationImpl" 前提是spring容器中有additionExaminationImpl bean--> /></aop:aspect></aop:config>
</beans>

spring(4)面向切面的Spring(AOP)相关推荐

  1. 《Spring实战》读书笔记-第4章 面向切面的Spring

    <Spring实战>是学习Spring框架的一本非常经典的书籍,之前阅读了这本书,只是在书本上写写画画,最近整理了一下<Spring实战>的读书笔记,通过博客的方式进行记录分享 ...

  2. 面向切面的 Spring —— 什么是面向切面编程?

    Q1:面向切面编程(AOP)解决什么问题? A1:把横切关注点与业务逻辑相分离. Q2:什么是横切关注点? A2:在软件开发中,散布于应用中多处的功能. 日志是应用切面的常见范例,但并不是切面适用的唯 ...

  3. spring boot 503_Spring实战读书笔记第4章 面向切面的Spring

    本章内容: 面向切面编程的基本原理 通过POJO创建切面 使用@AspectJ注解 为AspectJ切面注入依赖 在软件开发中,散布于应用中多的功能被称为横切关注点(cross-cutting con ...

  4. 面向切面的Spring

    2019独角兽企业重金招聘Python工程师标准>>> 前言 在软件开发中,散布于应用中多处的功能被称为横切关注点.这些横切关注点从概念上是与应用的业务逻辑相分离的.把这些横切关注点 ...

  5. Spring实战 | 第一部分 Spring的核心(第四章 面向切面的Spring)

    第四章 面向切面编程 面向切面编程的基本原理 通过POJO创建切面 使用@AspectJ注解 为AspectJ切面注入依赖 AspectJ是一个面向切面的框架,它扩展了java语言.AspectJ定义 ...

  6. 【Spring实战学习笔记】第4章 面向切面的Spring

    目录 4.1 什么是面向切面编程 4.2 通过切点来选择连接点 4.3 使用注解创建切面 4.4 在XML中声明切面 4.5 注入AspectJ切面 4.6 小结 在软件开发中,散布于应用中多处的功 ...

  7. Spring4详解系列(四)面向切面的Spring

    1.什么是面向切面编程 AOP(Aspect-Oriented Programming), 即面向切面编程, 它与 OOP( Object-Oriented Programming, 面向对象编程) ...

  8. Spring In Action 03 ---面向切面的Spring

    在系统中有些功能我们需要应用到程序的多个地方,但是我们又不想在每个点都明确的调用他.日志.安全和事务管理的确很重要,但他们是否是应用对象主动参与的行为呢?如果让应用对象只关注于自己所针对的业务领域问题 ...

  9. iOS面向切面的TableView-AOPTableView

    iOS面向切面的TableView-AOPTableView 这个是公司很久之前的开源项目,一个大牛写的,在项目中一直有在用,今天有空发了点时间看下如何实现,看了之后感觉挺有收获,故撰此文,分享给需要 ...

最新文章

  1. Windows Live Messenger  正式版已经发布
  2. Linux中的top命令查看内存和cpu信息
  3. subprocess 模块
  4. Hibernate中的核心接口query接口用法
  5. Go 函数特性和网络爬虫示例
  6. 航空机票预订c#代码_航空公司座位预订问题的C ++程序
  7. python基础入门(7)之元组
  8. jQuery万能浮动框插件测试
  9. 我的迅雷资源博客已经开通!
  10. Linux for Matlab中文注释乱码(亲测有效)
  11. Julia : 再谈HDF5 的save 和 load
  12. 关于为了吃瓜通宵7天写了一个网站却没钱买域名这件小事
  13. 【开源毕设】一款精美的家校互动APP分享——爱吖校推 [你关注的,我们才推](持续开源更新2)
  14. 图10——判断顶点u和顶点v是否存在简单路径
  15. oracle 取记录最大的那条记录_相机记录高三备考生的一天,看哭万人: 读书虽苦,却是最容易的那条路!...
  16. Exposure X7胶片滤镜模拟软件 PS/LR调色插件 500+特效预设
  17. 20191127上海出差总结
  18. springboot+vue企业人事人力资源管理系统java公司员工出差考勤办公OA系统
  19. 完整的写出一个微信小程序的电子商城的用户人脉关系网的所有功能,所包含的前台、中台、后台所有的用户功能与管理员功能以及维护人员及客服的所有功能需求。
  20. 6月5日(一些繁琐的事)

热门文章

  1. 2018-2019 ICPC Northwestern European Regional Programming Contest (NWERC 2018)
  2. Wizard of Orz CodeForces - 1467A
  3. splay/fhq-treap 问卷调查反馈—— [JSOI2008]火星人prefix(splay),Strange Queries(fhq-treap)
  4. 数据结构之线段树Ⅴ——(李超线段树)Robot,Product Sum,Building Bridges,Jump mission
  5. [贪心专题]CF549G,CF351E,CF226D,CF1276C,CF1148E,CF798D
  6. 树的合并(ybtoj-树上dp)
  7. YbtOJ#893-带权的图【高斯消元,结论】
  8. AT2165-[AGC006D]MedianPyramidHard【二分,贪心】
  9. jzoj3832-在哪里建酿酒厂【指针】
  10. jzoj6311-Mobitel【dp,整除分块】