实现Spring上下文,提供Bean创建的扩展

前言

上一节,我们已经完成通过 xml 配置文件 实现 Bean 的注入。这一节是重头戏,老实说,我现在都还弄的很明白。这是第二遍看这个过程了,还是有点云里雾里的。但是相对于第一次来说,已经上升了一个高度。 在这一节,会对 spring 创建 bean 的过程进行封装。并且提供 BeanPostProcessor,BeanFactoryPostProcessor等扩展接口。(这两个东西老强了) 上下文把整个创建过程包装起来,对外暴露一个简单的入口,其他的东西都在内部实现。(这个过程其实可以类比成 模板方法 是使用,我们直接使用就可以,并不需要知道内部的实现) 由于上下文已经封装好了整个bean的创建过程,内部实现对外是不开放的,所以提供了 BeanPostProcessor(bean 创建 之前处理,bean 创建之后处理)、BeanFactoryPostProcessor (对beanDifinition 创建后处理)给 开发者 的扩展接口,在创建bean的过程中,添加自己的实现逻辑。

实现

BeanPostProcessor Bean 创建完成前后扩展接口

它可以在 Bean 实例化、依赖注入、初始化前后等时刻对 Bean 进行一些额外的处理,例如修改 Bean 属性、动态代理等等。 这个类使用了模板方法模式。扩展类只需实现该接口,然后spring会在创建的bean的过程中调用这个方法完成 对bean的修改。 spring 在获取所有的 扩展类并完成扩展使用的是装饰器模式,每个 扩展类都可以类比成一个装饰器,然后通过责任链的方式完成调用。

**模板方法:**模板方法是一种行为设计模式,它定义了一个过程的骨架,并允许子类在不改变该过程结构的情况下重新定义某些步骤。 **装饰器模式:**装饰器模式是一种结构型设计模式,它允许动态地向对象添加新的行为,同时又不会改变其原有的行为。该模式通过一种装饰器类来包装原有的类,从而给对象增加新的功能。 责任链模式:责任链模式是一种行为型设计模式,它将多个处理器(Handler)组成一条链,用于依次处理请求,直到请求被处理完成为止。在责任链模式中,每个处理器都有一个指向下一个处理器的引用,从而形成了一条处理链。

在实际开发过程中,我们也可以尝试使用这些设计模式来优化我们的代码。在这个扩展接口的实现过程,我们可以学到 模板 +装饰器 +责任链的一种使用场景。很多时候,单独是设计模式并不能很好地解决问题,但是当我们把他们组合到一起的时候,他就会变成一种很优雅的解决方案.


/**
 * @author huangle
 * @date 2023/2/13 15:18
 */
public interface BeanPostProcessor {

    /**
     * 在 Bean 对象执行初始化方法之前,执行此方法
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    /**
     * 在 Bean 对象执行初始化方法之后,执行此方法
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

复制代码

BeanFactoryPostProcessor beanDefinition 加载完成后扩展接口

这个扩展设计跟上一个差不多,具体可以看上面的设计

public interface BeanFactoryPostProcessor {

    /**
     * 在所有的 BeanDefinition 加载完成后,实例化 Bean 对象之前,提供修改 BeanDefinition 属性的机制
     * @param beanFactory
     */
    void postProcessorBeanFactory(ConfigurableListableBeanFactory beanFactory);

}
复制代码

AbstractApplicationContext 统一处理抽象类

AbstractApplicationContext完成对逻辑过程的整合,定义统一处理流程,实现过程通过定义抽象方法,交给具体的实现类去完成。 这里其实就是对spring容器 初始化做一个 模板处理,只定义基本骨架,具体都交给后面的子类是完成。

public interface ConfigurableApplicationContext extends ApplicationContext{

    void refresh() throws BeansException;

}

/**
 * @author huangle
 * @date 2023/2/13 15:15
 */
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {

    /**
     * 模板方法,控制定义spring上下文的刷新与创建
     * @throws BeansException
     */
    @Override
    public void refresh() throws BeansException {
        // 1. 创建beanFactory,加载beanDefinition
        refreshBeanFactory();
        // 2. 获取 beanFactory
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        // 3. bean 实例化之前 执行 beanFactoryPostProcessor
        invokeBeanFactoryPostProcessors(beanFactory);
        // 4. beanPostProcessor 完成 bean 实例化后的注册操作
        registerBeanPostProcessors(beanFactory);
        // 5. 提前实例化 单例bean 对象
        beanFactory.preInstantiateSingletons();
    }

    protected abstract void refreshBeanFactory() throws BeansException;

    protected abstract ConfigurableListableBeanFactory getBeanFactory();

    /**
     * 初始化 BeanFactoryPostProcessor 处理器
     * @param beanFactory
     */
    private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory){
        Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
        for (BeanFactoryPostProcessor factoryPostProcessor : beanFactoryPostProcessorMap.values()) {
            // 处理 beanDifinition 扩展逻辑
            factoryPostProcessor.postProcessorBeanFactory(beanFactory);
        }
    }

    /**
     * 初始化 BeanPostProcessor 处理器
     * @param beanFactory
     */
    private void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory){
        Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
        for (BeanPostProcessor postProcessor : beanPostProcessorMap.values()) {
            beanFactory.addBeanPostProcessor(postProcessor);
        }
    }
}
复制代码

AbstractAutowireCapableBeanFactory#createBean 统一处理bean扩展逻辑

spring流程的核心类,所有的扩展都会在这里汇合,一同作用于spring创建bean的过程。

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

    private CglibSubclassingInstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

    @Override
    public Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) {
        Object bean = null;
        try {
            bean = createBeanInstance(beanDefinition, beanName, args);
            // 注入属性
            applyPropertyValues(beanName, bean, beanDefinition);
            // 提供给外部的扩展包装,执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法
            bean = initializeBean(beanName, bean, beanDefinition);
        } catch (Exception e) {
            throw new RuntimeException("bean create error!", e);
        }
        registerSingleton(beanName, bean);
        return bean;
    }
    private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) throws BeansException {
        // 1. 执行 BeanPostProcess before 操作
        Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);

        invokeInitMethods(beanName,wrappedBean,beanDefinition);

        // 2. 执行 BeanPostProcess after 操作
        wrappedBean = applyBeanPostProcessorsAfterInitialization(bean,beanName);

        return wrappedBean;
    }

    private void invokeInitMethods(String beanName, Object wrappedBean, BeanDefinition beanDefinition){

    }


    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        // 责任链模式 去获取到用户的扩展内容,然后在这里统一去处理
        for (BeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {
            Object current = beanPostProcessor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }


    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
       Object result = existingBean;
        for (BeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {
            Object current = beanPostProcessor.postProcessAfterInitialization(result, beanName);
            if (current == null){
                return result;
            }
            result = current;
        }
        return result;
    }
}
复制代码

测试

定义 MyBeanFactoryPostProcessor、MyBeanPostProcecssor 扩展内容

/**
 * @author huangle
 * @date 2023/3/3 15:55
 */
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessorBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        BeanDefinition userService = beanFactory.getBeanDefinition("userService");
        PropertyValues propertyValues = userService.getPropertyValues();
        PropertyValue propertyValue = new PropertyValue("nickname", "泰罗");
        propertyValues.addPropertyValue(propertyValue);
    }
}


/**
 * @author huangle
 * @date 2023/3/3 15:03
 */
public class MyBeanPostProcecssor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("userService".equals(beanName)) {
            UserService userService = (UserService) bean;
            userService.setName("海绵宝宝");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}
复制代码

业务逻辑

public class UserDao {

    public String getUserName(){
        return "Anoxia";
    }

}

public class UserService {

    private String name;

    private String nickname;

    private UserDao userDao;

    public UserService(String name) {
        this.name = name;
    }

    public String say(){
        return userDao.getUserName()+" say hello "+name + "and" + nickname;
    }
}


复制代码

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans>

    <bean id="userDao" class="cn.anoxia.springframework.beans.factory.support.UserDao"/>

    <bean id="userService" class="cn.anoxia.springframework.beans.factory.support.UserService">
        <property name="name" value="Anoxia"/>
        <property name="nickname" value="迪迦"/>
        <property name="userDao" ref="userDao"/>
    </bean>

    <bean id="myBeanPostProcecssor" class="cn.anoxia.springframework.beans.factory.support.MyBeanPostProcecssor"/>
    <bean id="myFactoryPostProcessor" class="cn.anoxia.springframework.beans.factory.support.MyBeanFactoryPostProcessor"/>

</beans>
复制代码

测试类

testContext 测试 手动创建工厂、创建处理类,注入。testContext1测试自动读取xml文件,自动注入

@Test
    public void testContext() throws BeansException {
        // 1. 初始化bean工厂
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 2. 定义读取xml处理器,加载bean
        XmlBeanDefinitionReader definitionReader = new XmlBeanDefinitionReader(beanFactory);
        definitionReader.loadBeanDefinitions("classpath:spring.xml");
        // 3. BeanDefinition 加载完成 & Bean实例化之前,修改 BeanDefinition 的属性值
        MyBeanFactoryPostProcessor factoryPostProcessor = new MyBeanFactoryPostProcessor();
        factoryPostProcessor.postProcessorBeanFactory(beanFactory);
        // 4. Bean实例化之后,修改 Bean 属性信息
        MyBeanPostProcecssor postProcecssor = new MyBeanPostProcecssor();
        beanFactory.addBeanPostProcessor(postProcecssor);

        UserService userService = (UserService) beanFactory.getBean("userService");
        System.out.println(userService.say());
    }

    @Test
    public void testContext1() throws BeansException {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
        UserService userService = (UserService) applicationContext.getBean("userService");
        System.out.println(userService.say());
    }
复制代码

测试结果

总结

这一节是学习spring过程中比较难的一节,如果学明白了这一节,对spring的扩展基本就理解了。学习的过程很枯燥,有很多时候,遇到一点问题就想放弃,没有一追到底的毅力。其实我感觉嗷,学起来累,学不明白,还是自己会的东西太少了,导致上下连不起了,贯通不了,导致寸步难行,继而放弃。 怎么说呢,写代码这东西真的没有什么捷径,多写,多写,多写。只看不写,每一次有问题又是去copy,永远也不会。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码解析2,部分摘抄 简单的说,在web容器中,通过ServletContext为Spring的IOC容器提供宿主环境,对应的建立起一个IOC容器的体系。其中,首先需要建立的是根上下文,这个上下文持有的对象可以有业务对象,数据存取对象,资源,事物管理器等各种中间层对象。在这个上下文的基础上,和web MVC相关还会有一个上下文来保存控制器之类的MVC对象,这样就构成了一个层次化的上下文结构。在web容器中启动Spring应用程序就是一个建立这个上下文体系的过程。Spring为web应用提供上下文扩展接口 WebApplicationContext: 如转载请注明,转载自:关注Java[http://www.gbsou.com] 本文链接: http://www.gbsou.com/2009/08/11/214.html - - Java代码 public interface WebApplicationContext extends ApplicationContext { //这里定义的常量用于在ServletContext中存取根上下文 String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT"; …… //对WebApplicationContext来说,需要得到Web容器的ServletContext ServletContext getServletContext(); } public interface WebApplicationContext extends ApplicationContext { //这里定义的常量用于在ServletContext中存取根上下文 String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT"; ...... //对WebApplicationContext来说,需要得到Web容器的ServletContext ServletContext getServletContext(); } 而一般的启动过程,Spring会使用一个默认的实现,XmlWebApplicationContext – 这个上下文实现作为在web容器中的根上下文容器被建立起来,具体的建立过程在下面我们会详细分析。 Java代码 public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext { /** 这是和web部署相关的位置信息,用来作为默认的根上下文bean定义信息的存放位置*/ public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml"; public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/"; public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml"; //我们又看到了熟悉的loadBeanDefinition,就像我们前面对IOC容器的分析中一样,这个加载工程在容器的refresh()的时候启动。 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException { //对于XmlWebApplicationContext,当然使用的是XmlBeanDefinitionReader来对bean定义信息来进行解析 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); } protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) { } //使用XmlBeanDefinitionReader来读入bean定义信息 protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { String[] configLocations = getConfigLocations(); if (configLocations != null) { for (int i = 0; i < configLocations.length; i++) { reader.loadBeanDefinitions(configLocations[i]); } } } //这里取得bean定义信息位置,默认的地方是/WEB-INF/applicationContext.xml protected String[] getDefaultConfigLocations() { if (getNamespace() != null) { return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX}; } else { return new String[] {DEFAULT_CONFIG_LOCATION}; } } } public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext { /** 这是和web部署相关的位置信息,用来作为默认的根上下文bean定义信息的存放位置*/ public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml"; public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/"; public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml"; //我们又看到了熟悉的loadBeanDefinition,就像我们前面对IOC容器的分析中一样,这个加载工程在容器的refresh()的时候启动。 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException { //对于XmlWebApplicationContext,当然使用的是XmlBeanDefinitionReader来对bean定义信息来进行解析 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); } protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) { } //使用XmlBeanDefinitionReader来读入bean定义信息 protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { String[] configLocations = getConfigLocations(); if (configLocations != null) { for (int i = 0; i < configLocations.length; i++) { reader.loadBeanDefinitions(configLocations[i]); } } } //这里取得bean定义信息位置,默认的地方是/WEB-INF/applicationContext.xml protected String[] getDefaultConfigLocations() { if (getNamespace() != null) { return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX}; } else { return new String[] {DEFAULT_CONFIG_LOCATION}; } } } 对于一个Spring激活的web应用程序,可以通过使用Spring代码声明式的指定在web应用程序启动时载入应用程序上下文(WebApplicationContext),Spring的ContextLoader是提供这样性能的类,我们可以使用 ContextLoaderServlet或者ContextLoaderListener的启动时载入的Servlet来实例化Spring IOC容器 – 为什么会有两个不同的类来装载它呢,这是因为它们的使用需要区别不同的Servlet容器支持的Serlvet版本。但不管是 ContextLoaderSevlet还是 ContextLoaderListener都使用ContextLoader来完成实际的WebApplicationContext的初始化工作。这个ContextLoder就像是Spring Web应用程序在Web容器中的加载器booter。当然这些Servlet的具体使用我们都要借助web容器中的部署描述符来进行相关的定义。 下面我们使用ContextLoaderListener作为载入器作一个详细的分析,这个Servlet的监听器是根上下文被载入的地方,也是整个 Spring web应用加载上下文的第一个地方;从加载过程我们可以看到,首先从Servlet事件中得到ServletContext,然后可以读到配置好的在web.xml的中的各个属性值,然后ContextLoder实例化WebApplicationContext并完成其载入和初始化作为根上下文。当这个根上下文被载入后,它被绑定到web应用程序的ServletContext上。任何需要访问该ApplicationContext的应用程序代码都可以从WebApplicationContextUtils类的静态方法来得到:
2.1. 简介 2.2. 控制反转(IoC)容器 2.2.1. 新的bean作用域 2.2.2. 更简单的XML配置 2.2.3. 可扩展的XML编写 2.2.4. Annotation(注解)驱动配置 2.2.5. 在classpath中自动搜索组件 2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@AspectJ 切面的支持 2.3.3. 对bean命名pointcut( bean name pointcut element)的支持 2.3.4. 对AspectJ装载时织入(AspectJ load-time weaving)的支持 2.4. 中间层 2.4.1. 在XML里更为简单的声明性事务配置 2.4.2. 对Websphere 事务管理的完整支持 2.4.3. JPA 2.4.4. 异步的JMS 2.4.5. JDBC 2.5. Web层 2.5.1. Spring MVC合理的默认值 2.5.2. Portlet 框架 2.5.3. 基于Annotation的控制器 2.5.4. Spring MVC的表单标签库 2.5.5. 对Tiles 2 支持 2.5.6. 对JSF 1.2支持 2.5.7. JAX-WS支持 2.6. 其他 2.6.1. 动态语言支持 2.6.2. 增强的测试支持 2.6.3. JMX 支持 2.6.4. 将Spring 应用程序上下文部署为JCA adapter 2.6.5. 计划任务 2.6.6. 对Java 5 (Tiger) 支持 2.7. 移植到Spring 2.5 2.7.1. 改变 2.8. 更新的样例应用 2.9. 改进的文档 I. 核心技术 3. IoC(控制反转)容器 3.1. 简介 3.2. 基本原理 - 容器和bean 3.2.1. 容器 3.2.2. 实例化容器 3.2.3. 多种bean 3.2.4. 使用容器 3.3. 依赖 3.3.1. 注入依赖 3.3.2. 依赖配置详解 3.3.3. 使用depends-on 3.3.4. 延迟初始化bean 3.3.5. 自动装配(autowire)协作者 3.3.6. 依赖检查 3.3.7. 方法注入 3.4. Bean的作用域 3.4.1. Singleton作用域 3.4.2. Prototype作用域 3.4.3. Singleton beans和prototype-bean的依赖 3.4.4. 其他作用域 3.4.5. 自定义作用域 3.5. 定制bean特性 3.5.1. 生命周期回调 3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. The ApplicationContext 3.8.1. BeanFactory 还是 ApplicationContext? 3.8.2. 利用MessageSource实现国际化 3.8.3. 事件 3.8.4. 底层资源的访问 3.8.5. ApplicationContext在WEB应用中的实例化 3.9. 粘合代码和可怕的singleton 3.10. 以J2EE RAR文件的形式部署Spring ApplicationContext 3.11. 基于注解(Annotation-based)的配置 3.11.1. @Autowired 3.11.2. 基于注解的自动连接微调 3.11.3. CustomAutowireConfigurer 3.11.4. @Resource 3.11.5. @PostConstruct 与 @PreDestroy 3.12. 对受管组件的Classpath扫描 3.12.1. @Component和更多典型化注解 3.12.2. 自动检测组件 3.12.3. 使用过滤器自定义扫描 3.12.4. 自动检测组件的命名 3.12.5. 为自动检测的组件提供一个作用域 3.12.6. 用注解提供限定符元数据 3.13. 注册一个LoadTimeWeaver 4. 资源 4.1. 简介 4.2. Resource接口 4.3. 内置 Resource 实现 4.3.1. UrlResource 4.3.2. ClassPathResource 4.3.3. FileSystemResource 4.3.4. ServletContextResource 4.3.5. InputStreamResource 4.3.6. ByteArrayResource 4.4. ResourceLoader接口 4.5. ResourceLoaderAware 接口 4.6. 把Resource作为属性来配置 4.7. Application context 和Resource 路径 4.7.1. 构造application context 4.7.2. Application context构造器中资源路径的通配符 4.7.3. FileSystemResource 说明 5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到错误信息 5.4. Bean处理和BeanWrapper 5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建的PropertyEditor实现 6. 使用Spring进行面向切面编程(AOP) 6.1. 简介 6.1.1. AOP概念 6.1.2. Spring AOP的功能和目标 6.1.3. AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个切入点(pointcut) 6.2.4. 声明通知 6.2.5. 引入(Introduction) 6.2.6. 切面实例化模型 6.2.7. 例子 6.3. 基于Schema的AOP支持 6.3.1. 声明一个切面 6.3.2. 声明一个切入点 6.3.3. 声明通知 6.3.4. 引入 6.3.5. 切面实例化模型 6.3.6. Advisor 6.3.7. 例子 6.4. AOP声明风格的选择 6.4.1. Spring AOP还是完全用AspectJ? 6.4.2. Spring AOP中使用@AspectJ还是XML? 6.5. 混合切面类型 6.6. 代理机制 6.6.1. 理解AOP代理 6.7. 以编程方式创建@AspectJ代理 6.8. 在Spring应用中使用AspectJ 6.8.1. 在Spring中使用AspectJ进行domain object的依赖注入 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用中使用AspectJ加载时织入(LTW) 6.9. 更多资源 7. Spring AOP APIs 7.1. 简介 7.2. Spring中的切入点API 7.2.1. 概念 7.2.2. 切入点运算 7.2.3. AspectJ切入点表达式 7.2.4. 便利的切入点实现 7.2.5. 切入点的超类 7.2.6. 自定义切入点 7.3. Spring的通知API 7.3.1. 通知的生命周期 7.3.2. Spring里的通知类型 7.4. Spring里的Advisor API 7.5. 使用ProxyFactoryBean创建AOP代理 7.5.1. 基础 7.5.2. JavaBean属性 7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对接口进行代理 7.5.5. 对类进行代理 7.5.6. 使用“全局”通知器 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动代理(autoproxy)”功能 7.9.1. 自动代理bean定义 7.9.2. 使用元数据驱动的自动代理 7.10. 使用TargetSource 7.10.1. 热交换目标源 7.10.2. 池化目标源 7.10.3. 原型目标源 7.10.4. ThreadLocal目标源 7.11. 定义新的Advice类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.2.1. Mock对象 8.2.2. 单元测试支持类 8.3. 集成测试 8.3.1. 概览 8.3.2. 使用哪个支持框架 8.3.3. 通用目标 8.3.4. JDBC测试支持 8.3.5. 常用注解 8.3.6. JUnit 3.8遗留支持 8.3.7. Spring TestContext Framework 8.3.8. PetClinic示例 8.4. 更多资源 II. 中间层数据访问 9. 事务管理 9.1. 简介 9.2. 动机 9.3. 关键抽象 9.4. 使用资源同步的事务 9.4.1. 高层次方案 9.4.2. 低层次方案 9.4.3. TransactionAwareDataSourceProxy 9.5. 声明式事务管理 9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 事务传播 9.5.8. 通知事务操作 9.5.9. 结合AspectJ使用 @Transactional 9.6. 编程式事务管理 9.6.1. 使用TransactionTemplate 9.6.2. 使用PlatformTransactionManager 9.7. 选择编程式事务管理还是声明式事务管理 9.8. 与特定应用服务器集成 9.8.1. IBM WebSphere 9.8.2. BEA WebLogic 9.8.3. Oracle OC4J 9.9. 常见问题的解决方法 9.9.1. 对一个特定的 DataSource 使用了错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 11.1.1. 选择一种工作模式 11.1.2. Spring JDBC包结构 11.2. 利用JDBC核心类控制JDBC的基本操作和错误处理 11.2.1. JdbcTemplate类 11.2.2. NamedParameterJdbcTemplate类 11.2.3. SimpleJdbcTemplate类 11.2.4. DataSource接口 11.2.5. SQLExceptionTranslator接口 11.2.6. 执行SQL语句 11.2.7. 执行查询 11.2.8. 更新数据库 11.2.9. 获取自动生成的主键 11.3. 控制数据库连接 11.3.1. DataSourceUtils类 11.3.2. SmartDataSource接口 11.3.3. AbstractDataSource类 11.3.4. SingleConnectionDataSource类 11.3.5. DriverManagerDataSource类 11.3.6. TransactionAwareDataSourceProxy类 11.3.7. DataSourceTransactionManager类 11.3.8. NativeJdbcExtractor 11.4. JDBC批量操作 11.4.1. 使用JdbcTemplate进行批量操作 11.4.2. 使用SimpleJdbcTemplate进行批量操作 11.5. 通过使用SimpleJdbc类简化JDBC操作 11.5.1. 使用SimpleJdbcInsert插入数据 11.5.2. 使用SimpleJdbcInsert来获取自动生成的主键 11.5.3. 指定SimpleJdbcInsert所使用的字段 11.5.4. 使用SqlParameterSource提供参数值 11.5.5. 使用SimpleJdbcCall调用存储过程 11.5.6. 声明SimpleJdbcCall使用的参数 11.5.7. 如何定义SqlParameters 11.5.8. 使用SimpleJdbcCall调用内置函数 11.5.9. 使用SimpleJdbcCall返回的ResultSet/REF Cursor 11.6. 用Java对象来表达JDBC操作 11.6.1. SqlQuery类 11.6.2. MappingSqlQuery类 11.6.3. SqlUpdate类 11.6.4. StoredProcedure类 11.6.5. SqlFunction类 11.7. 参数和数据处理的基本原则 11.7.1. 为参数设置SQL类型信息 11.7.2. 处理BLOB 和 CLOB对象 11.7.3. 在IN语句中传入一组参数值 11.7.4. 处理复杂类型的存储过程调用 12. 使用ORM工具进行数据访问 12.1. 简介 12.2. Hibernate 12.2.1. 资源管理 12.2.2. 在Spring容器中创建 SessionFactory 12.2.3. The HibernateTemplate 12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用服务器中使用Hibernate的注意事项 12.3. JDO 12.3.1. 建立PersistenceManagerFactory 12.3.2. JdoTemplate和JdoDaoSupport 12.3.3. 基于原生的JDO API实现DAO 12.3.4. 事务管理 12.3.5. JdoDialect 12.4. Oracle TopLink 12.4.1. SessionFactory 抽象层 12.4.2. TopLinkTemplate and TopLinkDaoSupport 12.4.3. 基于原生的TopLink API的DAO实现 12.4.4. 事务管理 12.5. iBATIS SQL Maps 12.5.1. 创建SqlMapClient 12.5.2. 使用 SqlMapClientTemplate 和 SqlMapClientDaoSupport 12.5.3. 基于原生的iBATIS API的DAO实现 12.6. JPA 12.6.1. 在Spring环境中建立JPA 12.6.2. JpaTemplate 和 JpaDaoSupport 12.6.3. 基于原生的JPA实现DAO 12.6.4. 异常转化 12.7. 事务管理 12.8. JpaDialect III. The Web 13. Web MVC framework Web框架 13.1. 概述 13.1.1. 与其他MVC实现框架的集成 13.1.2. Spring Web MVC框架的特点 13.2. DispatcherServlet 13.3. 控制器 13.3.1. AbstractController 和 WebContentGenerator 13.3.2. 其它的简单控制器 13.3.3. MultiActionController 13.3.4. 命令控制器 13.4. 处理器映射(handler mapping) 13.4.1. BeanNameUrlHandlerMapping 13.4.2. SimpleUrlHandlerMapping 13.4.3. 拦截器(HandlerInterceptor) 13.5. 视图与视图解析 13.5.1. 视图解析器(ViewResolver) 13.5.2. 视图解析链 13.5.3. 重定向(Rediret)到另一个视图 13.6. 本地化解析器 13.6.1. AcceptHeaderLocaleResolver 13.6.2. CookieLocaleResolver 13.6.3. SessionLocaleResolver 13.6.4. LocaleChangeInterceptor 13.7. 使用主题 13.7.1. 简介 13.7.2. 如何定义主题 13.7.3. 主题解析器 13.8. Spring对分段文件上传(multipart file upload)的支持 13.8.1. 介绍 13.8.2. 使用MultipartResolver 13.8.3. 在表单中处理分段文件上传 13.9. 使用Spring的表单标签库 13.9.1. 配置 13.9.2. form标签 13.9.3. input标签 13.9.4. checkbox标签 13.9.5. checkboxes标签 13.9.6. radiobutton标签 13.9.7. radiobuttons标签 13.9.8. password标签 13.9.9. select标签 13.9.10. option标签 13.9.11. options标签 13.9.12. textarea标签 13.9.13. hidden标签 13.9.14. errors标签 13.10. 处理异常 13.11. 惯例优先原则(convention over configuration) 13.11.1. 对控制器的支持:ControllerClassNameHandlerMapping 13.11.2. 对模型的支持:ModelMap(ModelAndView) 13.11.3. 对视图的支持:RequestToViewNameTranslator 13.12. 基于注解的控制器配置 13.12.1. 建立dispatcher实现注解支持 13.12.2. 使用@Controller定义一个控制器 13.12.3. 使用@RequestMapping映射请求 13.12.4. 使用@RequestParam绑定请求参数到方法参数 13.12.5. 使用@ModelAttribute提供一个从模型到数据的链接 13.12.6. 使用@SessionAttributes指定存储在会话中的属性 13.12.7. 自定义WebDataBinder初始化 13.13. 更多资源 14. 集成视图技术 14.1. 简介 14.2. JSP和JSTL 14.2.1. 视图解析器 14.2.2. 'Plain-old' JSPs versus JSTL 'Plain-old' JSP与JSTL 14.2.3. 帮助简化开发的额外的标签 14.3. Tiles 14.3.1. 需要的资源 14.3.2. 如何集成Tiles 14.4. Velocity和FreeMarker 14.4.1. 需要的资源 14.4.2. Context 配置 14.4.3. 创建模板 14.4.4. 高级配置 14.4.5. 绑定支持和表单处理 14.5. XSLT 14.5.1. 写在段首 14.5.2. 小结 14.6. 文档视图(PDF/Excel) 14.6.1. 简介 14.6.2. 配置和安装 14.7. JasperReports 14.7.1. 依赖的资源 14.7.2. 配置 14.7.3. 构造ModelAndView 14.7.4. 使用子报表 14.7.5. 配置Exporter的参数 15. 集成其它Web框架 15.1. 简介 15.2. 通用配置 15.3. JavaServer Faces 15.3.1. DelegatingVariableResolver 15.3.2. FacesContextUtils 15.4. Struts 15.4.1. ContextLoaderPlugin 15.4.2. ActionSupport Classes 15.5. Tapestry 15.5.1. 注入 Spring 托管的 beans 15.6. WebWork 15.7. 更多资源 16. Portlet MVC框架 16.1. 介绍 16.1.1. 控制器 - MVC中的C 16.1.2. 视图 - MVC中的V 16.1.3. Web作用范围的Bean 16.2. DispatcherPortlet 16.3. ViewRendererServlet 16.4. 控制器 16.4.1. AbstractController 和 PortletContentGenerator 16.4.2. 其它简单的控制器 16.4.3. Command控制器 16.4.4. PortletWrappingController 16.5. 处理器映射 16.5.1. PortletModeHandlerMapping 16.5.2. ParameterHandlerMapping 16.5.3. PortletModeParameterHandlerMapping 16.5.4. 增加 HandlerInterceptors 16.5.5. HandlerInterceptorAdapter 16.5.6. ParameterMappingInterceptor 16.6. 视图和它们的解析 16.7. Multipart文件上传支持 16.7.1. 使用 PortletMultipartResolver 16.7.2. 处理表单里的文件上传 16.8. 异常处理 16.9. Portlet应用的部署 IV. 整合 17. 使用Spring进行远程访问与Web服务 17.1. 简介 17.2. 使用RMI暴露服务 17.2.1. 使用RmiServiceExporter暴露服务 17.2.2. 在客户端链接服务 17.3. 使用Hessian或者Burlap通过HTTP远程调用服务 17.3.1. 为Hessian和co.配置DispatcherServlet 17.3.2. 使用HessianServiceExporter暴露你的bean 17.3.3. 在客户端连接服务 17.3.4. 使用Burlap 17.3.5. 对通过Hessian或Burlap暴露的服务使用HTTP Basic认证 17.4. 使用HTTP调用器暴露服务 17.4.1. Exposing the service object 17.4.2. 在客户端连接服务 17.5. Web Services 17.5.1. 使用JAX-RPC暴露基于servlet的web服务 17.5.2. 使用JAX-RPC访问web服务 17.5.3. 注册JAX-RPC Bean映射 17.5.4. 注册自己的JAX-RPC 处理器 17.5.5. 使用JAX-WS暴露基于servlet的web服务 17.5.6. 使用JAX-WS暴露单独web服务 17.5.7. 使用Spring支持的JAX-WS RI来暴露服务 17.5.8. 使用JAX-WS访问web服务 17.5.9. 使用XFire来暴露Web服务 17.6. JMS 17.6.1. 服务端配置 17.6.2. 客户端配置 17.7. 对远程接口不提供自动探测实现 17.8. 在选择这些技术时的一些考虑 18. Enterprise Java Beans (EJB) 集成 18.1. 简介 18.2. 访问EJB 18.2.1. 概念 18.2.2. 访问本地的无状态Session Bean(SLSB) 18.2.3. 访问远程SLSB 18.2.4. Accessing EJB 2.x SLSBs versus EJB 3 SLSBs 18.3. 使用Spring提供的辅助类实现EJB组件 18.3.1. EJB 2.x base classes 18.3.2. EJB 3 注入拦截 19. JMS (Java Message Service) 19.1. 简介 19.2. 使用Spring JMS 19.2.1. JmsTemplate 19.2.2. 连接工厂 19.2.3. 目的地管理 19.2.4. 消息侦听容器 19.2.5. 事务管理 19.3. 发送消息 19.3.1. 使用消息转换器 19.3.2. SessionCallback 和 ProducerCallback 19.4. 接收消息 19.4.1. 同步接收 19.4.2. 异步接收 - 消息驱动的POJO 19.4.3. SessionAwareMessageListener接口 19.4.4. MessageListenerAdapter 19.4.5. 事务中的消息处理 19.5. JCA消息端点的支持 19.6. JMS命名空间支持 20. JMX 20.1. 介绍 20.2. 将Bean暴露为JMX 20.2.1. 创建MBeanServer 20.2.2. 重用原有的MBeanServer 20.2.3. 延迟初始化的MBean 20.2.4. MBean的自动注册 20.2.5. 控制注册行为 20.3. 控制Bean的管理接口 20.3.1. MBeanInfoAssembler接口 20.3.2. 使用源码级元数据 20.3.3. 使用JDK 5.0的注解 20.3.4. 源代码级的元数据类型 20.3.5. AutodetectCapableMBeanInfoAssembler接口 20.3.6. 用Java接口定义管理接口 20.3.7. 使用MethodNameBasedMBeanInfoAssembler 20.4. 控制Bean的ObjectName 20.4.1. 从Properties读取Properties 20.4.2. 使用MetadataNamingStrategy 20.4.3. 元素 20.5. JSR-160连接器 20.5.1. 服务器端连接器 20.5.2. 客户端连接器 20.5.3. 基于Burlap/Hessian/SOAP的JMX 20.6. 通过代理访问MBean 20.7. 通知 20.7.1. 为通知注册监听器 20.7.2. 发布通知 20.8. 更多资源 21. JCA CCI 21.1. 简介 21.2. 配置CCI 21.2.1. 连接器配置 21.2.2. 在Spring中配置ConnectionFactory 21.2.3. 配置CCI连接 21.2.4. 使用一个 CCI 单连接 21.3. 使用Spring的 CCI访问支持 21.3.1. 记录转换 21.3.2. CciTemplate类 21.3.3. DAO支持 21.3.4. 自动输出记录生成 21.3.5. 总结 21.3.6. 直接使用一个CCI Connection接口和Interaction接口 21.3.7. CciTemplate 使用示例 21.4. 建模CCI访问为操作对象 21.4.1. MappingRecordOperation 21.4.2. MappingCommAreaOperation 21.4.3. 自动生成输出记录 21.4.4. 总结 21.4.5. MappingRecordOperation 使用示例 21.4.6. MappingCommAreaOperation 使用示例 21.5. 事务 22. Spring邮件抽象层 22.1. 简介 22.2. 使用Spring邮件抽象 22.2.1. MailSender 和 SimpleMailMessage 的基本用法 22.2.2. 使用 JavaMailSender 和 MimeMessagePreparator 22.3. 使用MimeMessageHelper 22.3.1. 发送附件和嵌入式资源(inline resources) 22.3.2. 使用模板来创建邮件内容 23. Spring中的定时调度(Scheduling)和线程池(Thread Pooling) 23.1. 简介 23.2. 使用OpenSymphony Quartz 调度器 23.2.1. 使用JobDetailBean 23.2.2. 使用 MethodInvokingJobDetailFactoryBean 23.2.3. 使用triggers和SchedulerFactoryBean来包装任务 23.3. 使用JDK Timer支持类 23.3.1. 创建定制的timers 23.3.2. 使用 MethodInvokingTimerTaskFactoryBean类 23.3.3. 最后:使用TimerFactoryBean来设置任务 23.4. SpringTaskExecutor抽象 23.4.1. TaskExecutor接口 23.4.2. TaskExecutor类型 23.4.3. 使用TaskExecutor 24. 动态语言支持 24.1. 介绍 24.2. 第一个示例 24.3. 定义动态语言支持的bean 24.3.1. 公共概念 24.3.2. JRuby beans 24.3.3. Groovy beans 24.3.4. BeanShell beans 24.4. 场景 24.4.1. Spring MVC控制器的脚本化 24.4.2. Validator的脚本化 24.5. Bits and bobs 24.5.1. AOP - 通知脚本化bean 24.5.2. 作用域 24.6. 更多的资源 25. 注解和源代码级的元数据支持 25.1. 简介 25.2. Spring的元数据支持 25.3. 注解 25.3.1. @Required 25.3.2. Spring中的其它@Annotations 25.4. Jakarta Commons Attributes集成 25.5. 元数据和Spring AOP自动代理 25.5.1. 基本原理 25.5.2. 声明式事务管理 V. 示例程序 26. 演示案例 26.1. 介绍 26.2. 使用动态语言实现Spring MVC控制器 26.2.1. 构建与部署 26.3. 使用SimpleJdbcTemplate和@Repository实现DAO 26.3.1. 域对象 26.3.2. Data Access Object 26.3.3. 构建 A. XML Schema-based configuration A.1. Introduction A.2. XML Schema-based configuration A.2.1. Referencing the schemas A.2.2. The util schema A.2.3. The jee schema A.2.4. The lang schema A.2.5. The jms schema A.2.6. The tx (transaction) schema A.2.7. The aop schema A.2.8. The context schema A.2.9. The tool schema A.2.10. The beans schema A.3. Setting up your IDE A.3.1. Setting up Eclipse A.3.2. Setting up IntelliJ IDEA A.3.3. Integration issues B. Extensible XML authoring B.1. Introduction B.2. Authoring the schema B.3. Coding a NamespaceHandler B.4. Coding a BeanDefinitionParser B.5. Registering the handler and the schema B.5.1. 'META-INF/spring.handlers' B.5.2. 'META-INF/spring.schemas' B.6. Using a custom extension in your Spring XML configuration B.7. Meatier examples B.7.1. Nesting custom tags within custom tags B.7.2. Custom attributes on 'normal' elements B.8. Further Resources C. spring-beans-2.0.dtd D. spring.tld D.1. Introduction D.2. The bind tag D.3. The escapeBody tag D.4. The hasBindErrors tag D.5. The htmlEscape tag D.6. The message tag D.7. The nestedPath tag D.8. The theme tag D.9. The transform tag E. spring-form.tld E.1. Introduction E.2. The checkbox tag E.3. The checkboxes tag E.4. The errors tag E.5. The form tag E.6. The hidden tag E.7. The input tag E.8. The label tag E.9. The option tag E.10. The options tag E.11. The password tag E.12. The radiobutton tag E.13. The radiobuttons tag E.14. The select tag E.15. The textarea tag F. Spring 2.5开发手册中文化项目 F.1. 声明 F.2. 致谢 F.3. 参与人员 F.4. 项目历程 表格清单 3.1. bean定义 3.2. Autowiring modes 3.3. 依赖检查方式 3.4. Bean作用域 3.5. Feature Matrix特性表 3.6. 内置事件 3.7. 过滤器类型 4.1. Resource strings 5.1. 属性示例 5.2. 内建的PropertyEditors 6.1. DefaultContextLoadTimeWeaver LoadTimeWeaversDefaultContextLoadTimeWeaver类和LoadTimeWeavers接口 6.2. aspectj-weaving属性值 9.1. 有关的设置 9.2. 设置 9.3. @Transactional 注解的属性 13.1. WebApplicationContext中特殊的bean 13.2. DispatcherServlet初始化参数 13.3. AbstractController提供的功能 13.4. 视图解析器 13.5. CookieLocaleResolver的属性 13.6. ThemeResolver的实现 14.1. 宏定义表 14.2. JasperReports View Classes 14.3. JasperReportsMultiFormatView默认Mapping Key映射 16.1. WebApplicationContext中特殊的Bean 16.2. DispatcherPortlet 的初始化参数 16.3. AbstractController提供的功能 19.1. JMS listener 元素的属性 19.2. JMS 元素的属性 19.3. JMS 元素的属性 20.1. 注册行为 20.2. 源代码级的元数据类型 20.3. 源代码级的元数据参数 21.1. Usage of Interaction execute methods 21.2. Usage of Interaction execute methods A.1. Eclipse XML editors D.1. Attributes D.2. Attributes D.3. Attributes D.4. Attributes D.5. Attributes D.6. Attributes D.7. Attributes D.8. Attributes E.1. Attributes E.2. Attributes E.3. Attributes E.4. Attributes E.5. Attributes E.6. Attributes E.7. Attributes E.8. Attributes E.9. Attributes E.10. Attributes E.11. Attributes E.12. Attributes E.13. Attributes E.14. Attributes

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值