Spring Framework

IoC容器

使用FactoryBean接口

  • Spring通过FactoryBean接口解决了不能用new创建依赖关系的问题。在创建事务性代理,从JNDI自动获取资源时,都不能用new来创建bean,这时就需要FactoryBean的实现来创建这些对象。FactoryBean是其他bean的工厂,它和任何正常bean一样在BeanFactory中配置,然而,当Spring用FactoryBean来满足一个依赖或查找请求时,它并不返回FactoryBean对象,而是调用FactoryBean的getObject()方法来返回此次调用的结果。

BeanFactoryPostProcessor

  • Spring会检测到实现了BeanFacoryPostProcessor接口的bean,在构造完成BeanFactory后,初始化其他任何bean之前初始化BeanFactoryPostProcessor的bean。
public interface BeanFactoryPostProcessor{
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
}
  • BeanFactory中使用BeanFactoryPostProcessor,回调处理函数postProcessBeanFactory并不会自动调用,但如果使用ApplicationContext后,这就不再是问题了。

BeanPostProcessor

  • BeanPostProcessor可以改变bean的类型(type)或行为(behavior),前者用于设置基于注解的依赖,提供初始和销毁的方法;后者用于动态语言bean,将@AspectJ注解转换成真正的切面(aspect)。

ApplicationContext

  • ApplicationContext是对BeanFactory的扩展,减少了与之交互所需的代码,任何在ApplicationContext中注册的BeanPostPorcessor和 BeanFactoryPostProcessor都会自动执行。ApplicationContext允许你以完全声明式地配置Spring的所有资源。相比于BeanFactory,ApplicationContext增加了如下的功能:
  • 国际化
  • 事件发布
  • 资源的管理和访问
  • 额外的生命周期接口
  • 改进了的基础组件自动化配置

Spring AOP

Spring AOP核心概念

  • joinpoint(连接点)
    程序执行中某个特别定义过的(well-defined)点,如调用某个方法,或方法调用本身,类的初始化,创建对象的实例等,Spring AOP只支持调用方法连接点。
  • advice(通知)
    某个joinpoint处执行的代码即为通知,有before advice,after advice。
  • pointcut(切入点)
    advice的执行可能会涉及多个joinpoint,这些joinpoint的集合即为切入点。某个方法的调用是连接点,而某个类所有方法调用的连接点的集合即为切入点。
  • aspect(切面)
    pointcut和advice的组合即为aspect,这个组合定义了执行的逻辑及执行的内容。
  • weaving(织入)
    将切面加入程序代码的过程即为weaving,包括静态AOP和动态AOP。
  • target(目标)或advised object(被通知对象)
    AOP操作的目标对象。
  • introduction(引入)
    introduction可以在对象中加入新的方法或属性,也可以让对象实现某个特定接口而无需显式地实现这个接口。Spring认为introduction是特殊的通知。
  • advisor(通知者)
    Spring AOP定义的接口(即为Spring AOP定义的aspect),包容多种advice的共性。

ProxyFactory和ProxyFactoryBean

  • ProxyFactory控制了Spring AOP的织入和创建代理的过程,步骤如下:
  1. 用setTarget()方法设定目标。
  2. ProxyFactory交由DefaultAopProxyFactory对象生成代理。
  3. DefaultProxyFactory再转交给Cglib2AopProxy或JdkDynamicProxy完成。
    ProxyFactory织入有两种方法来实现:
  • addAdvice()
    适合对target的所有方法执行通知的情形,内部实现将通知包装在DefaultPointcutAdvisor对象中。
  • addAdvisor()
    使用自定义的advisor,可以对advisor有更精确的控制,也可以向代理中添加introduction。

Spring AOP中的advisor和pointcut

public interface Pointcut{
    ClassFilter getClassFilter();
    MethodMatcher getMethodMatcher();
}
public interface ClassFilter{
    boolean matches(Class clazz);
}
public interface MethodMatcher{
    boolean matches(Method m, Class targetClass);
    boolean matches(Method m, Class targetClass, Object[] args);
    boolean isRuntime();//判断静态和动态
}
  • 如果是静态切入点,Spring会缓存MethodMatcher的结果。如果是动态切入点,Spring会先检测总的适用性,但以后每次调用还是会调用matches方法进行测试。
  • Spring提供的Pointcut实现,其中2个abstract打头的类用来简化创建静态和动态切入点。
实现类 说明
AbstractExpressionPointcut  
AbstractRegexpMethodPointcut  
AnnotationMatchingPointcut 对某些有特定注解的类实施切入。
AspectJExpressionPointcut 用AspectJ表达式来定义切入点,Spring只能定义方法的执行切入点。
ComposablePointcut 可以通过union,intersection等操作组合两个或两个以上切入点。
ControlFlowPointcut 某个方法中所有直接或间接调用的所有方法会成为切入点。
DynamicMethodMatcherPointcut 构建动态切入点的基类。
JdkRegexpMethodPointcut JDK1.4正则表达式定义的切入点。
NameMatchMethodPointcut 方法名列表定义的切入点。
StaticMethodMatcherPointcut 构建静态切入点的基类。
StaticMethodMatcherPointcutAdvisor  

Proxy

  • Proxy的核心功能是拦截方法调用,如有必要,相应的多个advice也会执行。advice的管理和调用都由Spring AOP完成,Proxy需要的只是拦截方法的调用并传递给Spring AOP。
  • 此外,Proxy还需要支持以下的特性:
  • 经过配置(ProxyFactory.setExposeProxy()),Proxy对象可通过AopContext暴露出来,这样,target就能够调用得到Proxy中的advised方法。
  • 默认情形下,所有的Proxy都实现了Advisor接口,这样Proxy生成后还可更改advice。
  • target中返回this对象的方法返回的是Proxy而不是target自身。

JDK动态代理

  • JDK代理只能代理接口,不能代理类。JDK代理会拦截所有的方法调用,并将其传至代理的invoke()方法,然后invoke()方法判断是否有通知,如有通知,去执行通知。缺点即是没有通知也会检查,并用反射执行,性能受影响。

CGLIB代理

  • CGLIB代理只会在首次创建时访问每个方法如何处理,接下来会生成真正的字节码,从而提高效率。

选用代理

  • 代理类时只能使用CGLIB。代理接口时有区别,调用setInterfaces会默认使用JDK代理,如果要改成CGLIB,必须调用setOptimize()方法,设定优化标志为true。

你可能感兴趣的:(Spring Framework)