zoukankan      html  css  js  c++  java
  • Spring学习进阶(二)Spring IoC

    在使用Spring所提供的各种丰富而神奇的功能之前,必须在Spring IoC容器中装配好Bean,并建立Bean与Bean之间的关联关系。
    控制反转(Inverser of Control ioc)是Spring容器的内核,AOP、声明式事务等功能都是在此基础上开花结果的。所谓Ioc,
    就是通过容器来控制业务对象之间的依赖关系,而非传统实现中,由代码直接操控、这也就是“控制反转”概念的所在:控制权
    由应用代码中转到了外部容器,控制权的转移,就是反转。控制权转移带来的好处就是降低了业务对象之间的依赖程度。
    BeanFactory和ApplicationContext:
    Spring通过一个配置文件描述了Bean和Bean之间的依赖关系,利用Java语言的反射功能实例化Bean并建立Bean之间的依赖关系。
    Spring的IoC容器在完成这些底层工作之后还提供了Bean实例缓存,生命周期管理,ean实例代理,事件发布,资源装载等高级服务。
    Bean工程(com.springframework.beans.factory.BeanFactory)是Spring框架核心的接口,它提供了高级IoC的高级配置机制,
    BeanFactory使管理不同类型的java对象成为可能,应用上下文(com.springframework.context.ApplicationContext)是建立在
    BeanFactory基础之上,提供了更多面向应用的功能,还提供了国际化支持和框架事件体系,更易于创建实际应用。一般称BeanFactory
    为IoC容器,而称ApplicationContext为应用上下文。
    区分:BeanFactory是Spring框架的基础设施,面向Spring本身;ApplciationContext面向使用Spring框架的开发者,几乎所有的应用
    场合都直接使用ApplicationContext而不是底层的BeanFactory。

    BeanFactory介绍:
    BeanFactory是一个工厂类,但它和传统的类工厂不同,传统的类工厂仅负责构造一个或几个类的实例,而BeanFactory是类的通用工厂,
    他可以创建并管理各种累的对象。这些可被创建和管理的对象本身没有什么特别之处,仅是一个POJO,Spring称这些被创建和管理的java
    对象为Bean。
    beans.xml:Car的配置文件

    beanfactory/BeanFactoryTest.java


    ApplicationContext介绍:
    ApplicationContext是由BeanFactory派生而来,提供了更多面向实际应用的功能,在BeanFactory中,很多功能都需要以编程的方式实现,
    而在ApplicationContext中则可以通过配置的方式实现。
    与BeanFactory初始化相似,ApplicationContext的初始化也很简单,如果配置文件防止在类路径下,则可以优先使用ClassPathXMLApplicationContext
    实现类。
    ApplicationContext ctx=new ClassPathApplicationContext("com/smart/context/beans.xml")
    对于ClassPathXMLApplicationContext来说com/smart/context/beans.xml相当于classpath:com/smart/context/beans.xml
    如果配置文件放置在文件系统的路径下,则可以优先考虑使用FileSystemXmlApplicationContext实现类
    ApplicationContext ctx=new FileSystemApplicationContext("com/smart/context/beans.xml")
    对于FileSystemApplicationContext来说com/smart/context/beans.xml相当于file:com/smart/context/beans.xml

    还可以指定一组配置文件,Spring会自动将多个配置文件在内存中“整合”成一个配置文件
    ApplicationContext ctx=new ClassPathXmlApplicationContext(new String[]{"conf/beans1.xml","conf/beans2.xml"})
    当然FileSystemXMLApplicationContext和ClassPathXmlApplicationContext都可以显示使用带资源类型前缀的路径,他们的区别在于。如果不显示
    指定资源类型前缀,句分别将路径解析为文件系统路径和类路径。
    在获取ApplicationContext实例后,就可以像BeanFactory一样调用getBean(beanName)返回Bean了,ApplicationContext的初始化和BeanFactory
    的初始化有一个重大的区别:BeanFactory在初始化容器时,并未实例化Bean,直到第一个访问某个Bean时才实例化目标Bean;而ApplicationContext在
    初始化应用上下文时就实例化所有单实例的Bean.因此ApplicationContext的初始化时间会比BeanFactory稍长一些,不过稍后的调用则没有“第一次惩罚”
    的问题。
    Spring3.0之处基于类注解的配置方式,主要功能来自于Spring的一个名为JavaConfig的子项目。一个标注@Configuration注解的POJO即可提供Spring
    所需的Bean配置信息。

    context/Beans.java context/AnnotationApplicationContext.java

    WebApplicationContext类体系结构:
    WebApplicationContext是专门为Web应用准备的,它允许从相对于Web根目录的路径中装载配置文件,完成初始化工作。从WebApplicationContext中
    可以获得ServletConfig的引用,整个Web应用上下文对象将作为属性放置到ServletContext中,以便Web应用环境可以访问Spring应用上下文,Spring
    为此还专门提供一个工具类WebApplicationContextUtils,通过该类的getWebApplicationContext(servletContext sc)方法。即可以从ServletContext
    中获取WebApplicationContext实例。
    WebApplicationContext初始化:
    WenApplicationContext的初始化方式和BeanFactory,ApplicationContext的初始化方式有所区别,因为WebApplicationContext需要ServletContext实例,
    也就是说必须在拥有Web容器的前提下才能完成启动的工作。可以在web.xml中配置自动的servlet或定义web容器监听器(ServletContextListener)
    Spring分别提高了用于启动WebApplicationContext的servlet和web容器监听器。
    org.springframework.web.context.Context.ContextLoaderServlet
    org.springframework.web.context.Context.ContextLoaderListener

    通过Web容器监听器引导:
    <!--指定配置文件-->
    <context-param>
    <param-name>contextConfiguration</param-name>
    <param-value>/WEB-INF/viewspace-dao.xml,/WEB-INF/viewspace-service.xml,</param-value>
    </context-param>
    <!--声明web容器监听器-->
    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    ContextLoaderListener通过web容器上下文参数contextConfigLocation获取Spring配置文件的位置,可以指定多个配置文件,用逗号,空格或分号分割
    对于未带资源类型前缀的配置文件路径,WebApplicationContext默认这些路径是相对于Web的部署根路径。
    在不支持容器监听器的低版本web容器中,可采用ContextLoaderServlet来完成相同的工作。
    <!--指定配置文件-->
    <context-param>
    <param-name>contextConfiguration</param-name>
    <param-value>/WEB-INF/viewspace-dao.xml,/WEB-INF/viewspace-service.xml,</param-value>
    </context-param>
    <!--声明自动启动的servlet-->
    <listener>
    <servlet-name>springContextLoaderServlet</servlet-name>
    <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
    <!--启动顺序-->
    <load-on-startup>1</load-on-startup>
    </listener>
    WebApplicationContext需要使用日志功能,
    指定Log4J配置文件时启动Spring web应用上下文。
    <!--指定配置文件-->
    <context-param>
    <param-name>contextConfiguration</param-name>
    <param-value>/WEB-INF/viewspace-dao.xml,/WEB-INF/viewspace-service.xml</param-value>
    </context-param>
    <!--指定log4j配置文件位置-->
    <context-param>
    <param-name>log4jConfiguration</param-name>
    <param-value>/WEB-INF/log4j.properties</param-value>
    </context-param>
    <!--装载log4j配置文件的自启动servlet-->
    <servlet>
    <servlet-name>log4jConfiguration</servlet-name>
    <servlet-class>org.springframework.web.util.Log4jConfigServlet</servlet-class>
    <load-on-start-up>1</load-on-start-up>
    </servlet>
    <!--声明web容器监听器-->
    <listener>
    <servlet-name>springContextLoaderServlet</servlet-name>
    <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
    <!--启动顺序-->
    <load-on-startup>1</load-on-startup>
    </listener>

    使用@Configuration的java类提供配置信息的信息在web.xml中做如下配置:
    <web-app>
    <display-name>Archetype Created Web Application</display-name>
    <!--通过指定context参数,让spring使用AnnotationConfigWebApplicationContext而非XMLWebApplicationContext启动容器-->
    <context-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </context-param>
    <!--指定标注了@Configuration的配置类,多个可以使用逗号分开-->
    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>com.smart.AppConfig1</param-value>
    </context-param>
    <!--ContextLoaderListener监听器将根据上面配置使用AnnotationConfigWebApplicationContext根据contextConfigLocation指定的配置类启动Spring容器-->
    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    </web-app>
    ContextLoaderListener如果发现配置了contextClass上下文参数,就会使用参数所指定的WebApplicationContext实现类来初始化容器,该实现类会根据contextConfigLocation
    上下文参数指定的@Configuration的配置类所提供的Spring配置信息来初始化容器。

    资源加载:
    为了访问不同类型的资源,必须使用相应的Resource实现类,Spring提供了一个强大的加载资源的机制,不但可以通过classpath file等资源地址前缀来加载
    识别不同的资源类型,还支持Ant风格带通配符的资源地址。
    classpath: classpath:com/smart/beanfactory/beans.xml 从类路径中加载资源,classpath:和classpath:/是等价的,都是相对于类的根
    路径,资源文件可以在标准的文件系统中,也可以在jar或zip的类包中
    file: file:/conf.com.smart/smart/beanfactory/beans.xml 使用UrlResource从文件系统目录中装载资源,可采用绝对或相对路径
    http:// http://www.smart.com/resource/beans.xml 使用UrlResource从web服务器中装载资源
    ftp:// ftp://www.smart.com/resource/beans.xml 使用UrlResource从ftp服务器中装载资源
    没有前缀 com/smart/beanfactory/beans.xml 根据ApplicationContext具体实现类采用对应类型的Resource


    Bean装配:
    要使应用程序中的Spring容器成功启动,需要同时具备以下3方面的条件:
    Spring框架的雷暴都已经放到应用程序的类路径下
    应用程序为Spring提供玩呗的Bean配置信息
    Bean的类都已经放到应用程序的类路径下
    Spring启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表,然后根据这张注册表实例化Bean,装配好Bean之间的依赖关系
    为上层应用提供准备就绪的运行环境。
    Bean的配置信息是Bean的元数据信息,由4方面组成:
    Bean的实现类
    Bean的属性信息,如数据源的连接数,用户名密码等
    Bean的依赖关系,Spring根据依赖关系配置完成Bean之间的装配
    Bean的行为配置,如生命周期范围及生命周期各过程的回调函数等。
    Bean元数据信息在Spring容器中的内部对应物是由一个个BeanDefinition形成的Bean注册表,Spring实现了Bean原数据信息内部表示信息和外部表示的解耦。
    Bean配置信息定义了Bean的实现和依赖院系,Spring容器根据各种形式的Bean配置信息在容器内部建立Bean定义注册表,然后根据注册表加载,
    实例化Bean,并建立Bean和Bean的依赖关系,最后将这些准备就绪的Bean放到Bean缓存池中,以供外层的应用程序调用。



    Bean基本配置:
    装配一个Bean:
    在Spring容器的配置文件中,定义一个简要Bean的配置片段 <bean id="foo" class="com.smart.bean.Foo"/>
    一般情况下,Spring IoC容器中的一个Bean即对应配置文件中的一个<bean>.通过heyBean("id")即可获得对应的Bean,在容器中起到定位查找的作用,是外部程序和Spring IoC容器进行交互的桥梁,
    class属性指定了Bean对应的实现类

    Bean的命名:
    一般情况下,在配置一个Bean时,需要为其指定一个id属性作为Bean的名称。id在IoC容器中是唯一的,而且还必须遵循XML的命名规则(字母开始,后面可以是字母,数字,连字符,下划线,
    句号,冒号等),IoC不允许出现两个ID相同的Bean但是允许出现两个name相同的bean。如果id和name都没有指定则使用全限定类名作为bean的名称。

    属性注入:
    属性置入即通过setXXX()方法注入Bean的属性值或依赖对象,由于属性注入方式具有可选择性和灵活性的特定。因此比较普遍使用。
    属性注入要求bean提供一个默认的构造函数,并为需要注入的熟悉提供对应的Setter方法,Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter注入属性值,
    属性注入配置:
    <bean id="car" class="com.smart.ditype.Car">
    <property name="maxSpeed"><value>200</value></property>
    <property name="brand"><value>BMW</value></property>
    <property name="price"><value>2000000</value></property>
    </bean>
    构造函数注入:
    保证一些必要的属性在Bean实例化时就得到设置,并且确保了Bean实例在实例化后就可以使用
    按照类型匹配注入
    eg:
    public Car(String brand,double price){
    this.brand=brand;
    this.price=price;
    }
    =====>
    <bean id="car" class="com.smart.ditype.Car">
    <constructor-arg type="java.lang.String">
    <value>BMW</value>
    </constructor-arg>
    <constructor-arg type="double">
    <value>20000</value>
    </constructor-arg>
    </bean>
    实构造函数注入和属性注入都各有优缺点,Spring并没有强制用户使用哪一种方式,用户完全可以根据偏好自己选择,在某种情况下使用构造函数注入,而在另一些情况下使用属性注入,


    注入参数详解:
    <ref>元素可以通过以下3个属性引用容器中其他的bean.
    bean:通过该属性可以引用同一容器或父容器的Bean,这是最常见的形式
    local:通过该属性只能引用统一配置文件中的Bean他可以利用XML解析器自动检验引用的合法性,以便在开发编写配置时能够及时发现并纠正配置的错误
    parent:引用父容器中的Bean,如<ref parent="car">的配置说明car的Bean是父容器中的Bean
    集合类型属性:
    public class Boss {
    private List favorites=new ArrayList();
    private Map jobs=new HashMap();
    private Properties mails=new Properties();

    public Properties getMails() {
    return mails;
    }

    public void setMails(Properties mails) {
    this.mails = mails;
    }
    public Map getJobs() {
    return jobs;
    }

    public void setJobs(Map jobs) {
    this.jobs = jobs;
    }

    public List getFavorites() {
    return favorites;
    }

    public void setFavorites(List favorites) {
    this.favorites = favorites;
    }
    }


    注入:
    <bean id="boss1" class="com.smart.attr.Boss">
    <property name="favorites">
    <list>
    <value>看报</value>
    <value>篮球</value>
    <value>足球</value>
    </list>
    </property>
    <property name="jobs">
    <map>
    <entry>
    <key><value>AM</value></key>
    <value>会见客户</value>
    </entry>
    <entry>
    <key><value>PM</value></key>
    <value>公司内部会议</value>
    </entry>
    </map>
    </property>
    <property>
    <prop key="jobMail">john-office@smart.com</prop>
    <prop key="lifeMail">john-life@smart.com</prop>
    </property>
    </bean>

    自动装配:
    Spring IOC容器了解容器中所有Bean的配置信息,此外通过java反射机制可以获知实现类的结构信息。掌握容器中所有Bean的信息后,Spring IoC容器就可以
    按照某种规则对容器中的Bean进行自动配置。Bean元素提供了一个指定自动装配类型的属性autowire="<自动装配类型>"
    byName:根据名称进行自动装配。
    byType:根据类型进行自动配置。
    constructor:与byType类似,只不过他是根据构造函数注入而言的
    autodetect:根据bean的自省机制决定采用byType还是constructor进行自动装配。

    <beans>元素标签中的default-autowire属性可以配置全局自动匹配,默认设置为no,表示不启用。

    Bean作用域:在配置文件中定义Bean时,用户不但可以配置Bean的属性值以及相互之间的依赖关系,还可以定义Bean的作用域
    作用域类型:
    singleton:在Spring IoC容器中仅存在一个Bean实例,Bean以单实例的方式存在。
    prototype:每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行new XxxBean()的操作
    request:每次http请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
    session:同一个Http Session共享一个Bean,不同HTTP Session使用不同的Bean,该作用域仅适用于WebApplicationContext环境
    globalSession:同一个全局Session共享一个Bean,一般用于Portlet应用环境,该作用域仅适用于WebApplicationContext环境、
    Spring中注解:
    @Repository:用于对DAO实现类进行标注
    @Service:用于对Service实现类进行标注
    @Controller:用于对Controller实现类进行标注

    通过<context:component-scan>定义扫描的包
    <context:include-scan>表示要包含的目标类
    <context:exclude-scan>表示要排除在外的目标类
    过滤表达式:
    annotation:所有标注了XxxAnnotation的类,该类型采用目标类是否标注了某个注解进行过滤 com.smart.XxxAnnotation
    assignable:所有继承或扩展XxxService的类,该类型采用目标类是否继承或扩展某个特定类进行过滤 com.smart.XxxService
    aspectj:所有类名以Service结束的类及集成或扩展他们的类, com.smart..*Service+
    regex:正则表达式过滤 com.smart.anno.*
    custom:采用XxxTypeFile通过代码的方式根据过滤规则,该类型必须事先TypeFilter接口 com.smart.XxxTypeFilter

    自动装配Bean:Spring通过使用@Autowired注解实现Bean的依赖注入,如果容器中没有一个和标注变量类型匹配的Bean,Spring容器会启动时抛出NoSuchBeanDefinitionException
    异常,如果希望Spring即使找不到匹配的Bean完成注入也不要抛出异常,那么就可以使用@Autowired(require=false)进行标注。
    如果容器中有一个以上匹配的Bean,可以通过@Qualifier注解限定Bean的名称

    基于java类的配置:
    普通的POJO只要标注@Configuration注解,就可以为Spring容器提供Bean定义的信息了,每个标注了@Bean的类犯法都相当于提供一个Bean的定义信息、

    Bean不同配置方式比较
    1.基于XML配置
    定义:在XML文件中通过<bean>元素定义Bean,例如<bean class="com.bbt.UserDao"/>
    名称:通过<bean>的id或name属性定义,例如:<bean id="userDao" class="com.bbt.UserDao">默认名称为com.bbt.UserDao#0
    注入:通过<property>子元素或通过p命名空间的动态属性,如p:userDao-ref="userDao"进行注入
    生命过程方法:通过<bean>的init-method和destroy-method属性指定Bean实现类的方法名,最多只能指定一个初始化和一个销毁方法
    作用范围:通过<bean>的scope属性指定,如<bean class="com.bbt.UserDao" scope="prototype">
    延迟初始化:通过<bean>的lazy-init属性指定,默认为default,继承与<beans>的default-lazy-init设置,该值默认为false
    2.基于注解配置
    定义:在Bean实现类处通过标注@Component或衍型类(@Repository @Service @Controller)定义Bean
    名称:通过注解的value属性定义,如@Component("userDao")默认名称为小写字母打头的类名(不带包名)userDao
    注入:通过在成员变量或方法入参处标注@Autowired,按类型匹配自动注入。还可以配合使用@Qualifier按名称匹配方式注入
    生命过程方法:通过在目标方法上标注@PostConstruct和@PreDestroy注解指定初始化或销毁方法,可以定义任意多个方法
    作用范围:通过在类定义处标注@Scope指定。如@Scope("prototype")
    延迟初始化:通过在类定义处标注@lazy指定,如@Lazy(true)
    3.基于Java类配置
    定义:在标注了@Configuration的java类中,通过在类方法上标注@Bean定义一个Bean,方法必须提供Bean的实例化逻辑
    名称:通过@Bean的name属性定义,如@Bean("userDao")默认名称为方法名
    注入:比较灵活,可以在方法处通过@Autowired使方法入参绑定bean,然后在方法中通过代码进行注入,还可以通过调用配置类的@Bean方法进行注入
    生命周期方法:通过@Bean的initMethod或destoryMethod指定一个初始化或销毁方法。对于初始化方法来说,可以直接在方法内部通过代码的方式灵活初始化逻辑
    作用范围:通过在Bean方法定义处标注@Scope指定
    延迟初始化:通过在Bean方法定义处标注@Lazy指定

    Bean不同配置方式的适用场合
    基于XML配置:Bean实现类来源于第三方类库,如DataSource,JdbcTemplate等,因无法在类中标注注解,通过XML配置方式较好。命名空间的配置,如aop context等,只能采用基于XML的配置
    基于注解配置:Bean的实现类是当前项目开发的,可以直接在Java类中基于注解的配置
    基于Java类配置:基于Java类配置的优势在于可以通过代码控制Bean初始化的整体逻辑。所以如果实例化Bean的逻辑比较复杂,则比较适合用基于Java类配置的方式
  • 相关阅读:
    win10使用WampServer部署magento
    JavaScript的this详解
    jQuery的css
    jQuery.cssHooks
    jQuery属性
    jQuery选择器
    ajax中的stasus错误详解
    ajax
    js数组中的注意
    js的严格模式
  • 原文地址:https://www.cnblogs.com/dream-to-pku/p/5706563.html
Copyright © 2011-2022 走看看