• SpringIoc


    IoC(控制反转,Inverse of Control)是Spring容器的内核

    BeanFactory和ApplicationContxt
    Bean工厂是Spring框架最核心的接口。应用上下文ApplicationContext建立在BeanFactory基础之上
    XmlBeanFactory通过Resource装载Spring配置信息并启动容器,然后通过getBean从容器中获取对象
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    Resource res = resolver.getResource("classpath:com/smart/beanfactory/beans.xml");
    BeanFactory bf = new XmlBeanFactory(res);


    如果BeanFactory是Spring的心脏,那么SpplicationContext就是完整的身躯
    ApplicationContext ctx = new ClassPathXmlApplicationContext("com/smart/context/beans.xml");
    如果放在文件系统路径下:
    ApplicationContext ctx = new FileSystemXmlApplicationContext("com/smart/context/beans.xml");

    Spring3.0支持基于类注解的配置方式,主要功能来自JavaConfig的子项目。标注@Configuration注解的pojo即可提供Spring所需的Bean配置信息
    @Configuration
    public class Beans {

    @Bean(name = "car")
    public Car buildCar(){
    Car car = new Car();
    car.setName("红旗");
    return car;
    }
    }
    public class AnnotationApplicationContext {
    public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(Beans.class);
    Car car = ctx.getBean("car", Car.class);
    }
    }
    WebApplicationContext类体系结构
    webApplicationContext是专门为Web应用准备的。允许从相对Web根目录的路径中装载配置文件,完成初始化工作。WebApplicationContext可以获得ServletContext的引用,整个Web应用上下文对象作为属性放置到ServletContext中。
    初始化需要ServletContext实例,借助web.xml中配置自启动的Servlet或者Web容器监听器(ServletContextListener)可以完成。
    用于启动WebApplicationContext的Servlet和Web容器监听器:
    org.springframework.context.COntextLoaderServlet
    org.springframework.web.context.ContextLoaderListener

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
    /WEB-INF/viewspace-dao.xml, /WEB-INF/viewspace-service.xml
    </param-value>
    </context-param>
    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    ContextLoaderListener通过web容器上下文参数contextConfigLocation获取Spring配置文件的位置。指定多个用逗号、空格或分号分隔均可。默认路径是相对于web的部署根路径
    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/viewspace-dao.xml, /WEB-INF/viewspace-service.xml</param-value>
    </context-param>
    <servlet>
    <servlet-name>springContextLoaderServlet</servlet-name>
    <servlet-class>org.springframework.context.COntextLoaderServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>
    WebApplicationContext需要日志功能,用户可以将Log4J配置文件放置到类路径WEB-INF/classes下,此时Log4J引擎即可顺利启动。如果Log4J配置文件放置在其他位置,还比须在web.xml中指定Log4J的配置文件位置。Spring为Log4J引擎提供了两个类似于启用WebApplicationContext的实现类:Log4JConfigServlet和Log4JConfigListener,不管采用哪种方式都必须能保证在装在Spring的配置文件之前先装载Log4J配置信息
    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/viewspace-dao.xml, /WEB-INF/viewspace-service.xml</param-value>
    </context-param>
    <!-- 指定Log4J的配置文件位置 -->
    <context-param>
    <param-name>Log4JConfigLocation</param-name>
    <param-value>/WEB-INF/log4j.properties</param-value>
    </context-param>

    <!-- 装载Log4J配置文件的自启动Servlet -->
    <servlet>
    <servlet-name>log4JConfigServlet</servlet-name>
    <servlet-class>org.springframework.web.util.Log4JConfigServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
    <servlet-name>springContextLoaderServlet</servlet-name>
    <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
    </servlet>
    使用监听器的话,必须将Log4JConfigListener放置在ContextLoaderListener的前面。采用以上的配置方式,Spring将自动使用XmlWebApplicationContext启动Spring容器,即通过XML文件为Spring容器提供Bean的配置信息。

    如果使用@Configuration的Java类提供配置信息,则web.xml的配置需要如下配置:
    <web-app>
    <!-- 通过指定context参数,让Spring使用AnnotationConfigWebApplicationContext而非XmlWebApplicationContext启动容器 -->
    <context-param>
    <param-name>contextClass</param-name>
    <param-valud>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>

    资源加载:
    为了访问不同类型的资源,需要使用响应的Resource实现类,这样比较麻烦。Spring提供了一个强大的加载资源的机制,不仅能够通过"classpath:"、"file:"等资源地址前缀识别不同的资源类型,还支持Ant风格带通配符的资源地址。
    资源地址前缀 对应资源类型
    classpath: 从类路径中加载资源,classpath:和classpath:/是等价的,都是相对于类的跟路径。资源文件可以在标准的文件系统中,也可以在.jar或者.zip的类包中
    file: 使用URLResource从文件系统目录中装载资源,可采用绝对或相对路径
    http:// 使用URLResource从web服务器中装载资源
    ftp:// 使用URLResource从FTP服务器中装载资源
    没有前缀: 根据ApplicationContext具体实现类采用类型的Resource
    其中和"classpath:"对应的还有“classpath*:”前缀。假设有多个jar包或者文件系统类路径下都有一个相同的包名,“classpath:”只会在第一个加载的com.smart包下查找,而"classpath*:"会扫描所有这些JAR包及类路径下出现的com.smart类路径。
    Ant风格资源地址支持三种通配符:
    ?:匹配文件名中的一个字符
    *:匹配文件命中的任意个字符
    **:匹配多层路径

    Bean装配:
    要是应用程序中的Spring容器成功启动,需要同时满足以下3方面的条件
    Spring框架的类包都已经放到应用程序的类路径下
    应用程序为Spring提供完备的Bean配置信息

    bean命名:
    id满足xml对id的规范
    name属性进行命名属性上没有字符上的限制
    spring不允许出现两个相同id的bean,但却可以出现两个相同name的bean,如果有多个name相同的bean,getBean(beanName)获取的是最后声明的bean
    如果id和name都未指定,spring自动将全限定类名作为bean的名称
    如果id和name都未指定,且有多个同类的bean的话,获取指定bean应该是getBean("com.smart.Car");getBean("com.smart.Car#1)分别获得第一个第二个。

    依赖注入:
    属性注入:
    <bean id="car" class="com.smart.Car">
    <property name="name">
    <value>小汽车</value>
    </property>
    </bean>
    一般情况下,java的属性变量名都以小写字母起头,如maxSpeed。但也存在特殊的情况,考虑到一些特定意义的大写英文缩略词,javaBean也允许大写字母起头的属性变量名,不过必须满足“变量的前两个字母要么全部大写,要么全部小写”的要求。
    构造函数注入:
    类型确定位置:
    <bean id="car1" class="com.smart.ditype.Car">
    <constructor-arg type="java.lang.String">
    <value>红旗CA72</value>
    </constructor-arg>
    <constructor-arg type="double">
    <value>2000</value>
    </constructor-arg>
    </bean>
    索引确定位置:
    <bean id="car2" class="com.smart.Car">
    <constructor-arg index="0" value="红旗CA72"/>
    <constructor-arg index="1" value="中国一汽">
    </bean>
    索引和类型也可以联合使用。
    自身类型反射注入:
    <bean id="boss" class="com.smart.Boss">
    <constructor-arg>
    <ref bean="car"/>
    </constructor>
    </bean>
    注意不要出现循环依赖。

    注入参数:
    1、字面量
    value标签方式注入
    <bean id="car" class="com.smart.Car">
    <property name="maxSpeed">
    <value>200</value>
    </property>
    </bean>
    2、引用其他bean:
    <bean id="car" class="com.smart.Car"/>
    <bean id="boss" class="com.smart.Boss">
    <property name="car">
    <ref bean="car"></ref>
    </property>
    </bean>
    如果有两个配置文件,其中一个呗另一个加载。两个配置文件里面都有同样命名的bean。如何选择引用哪个呢?
    <!-- 该Bean和父容器的Car Bean具有相同的id -->
    <bean id="Car" class="com.smart.Car">
    <property name="brand" value="吉利CT5"/>
    </bean>
    <bean id="boss" class="com.smart.Boss">
    <property name="car">
    <!-- 引用父容器中的car,而非这里定义的Bean。如果采用<ref bean="car">将引用本容器处的car -->
    <ref parent="car"/>
    </property>
    </bean>
    3、集合类型属性
    List:
    <bean id="boss1" class="com.smart.Boss">
    <property name="factorites">
    <list>
    <value>看报</value>
    <value>赛车</value>
    </list>
    </property>
    </bean>
    Map:
    <bean id="boss1" class="com.smart.Boss">
    <property name="jobs">
    <map>
    <entry>
    <key><value>AM</value></key>
    <value>会见客户</value>
    </entry>
    </map>
    </property>
    </bean>
    如果某一Map元素的键和值都是对象,则可以采取以下的配置方式:
    <entry>
    <key><ref bean="keyBean"/></key>
    <ref bean="valueBean"/>
    </entry>
    Properties:
    <bean id="boss1" class="com.smart.Boss">
    <props>
    <prop key="jobMail">john-office@smart.com</prop>
    </props>
    </bean>
    可以使用util命名空间配置集合类型的Bean。如:
    <util:list id="favoriteList" list-class="java.util.LinkedList">
    <value>看报</value>
    <value>赛车</value>
    </util:list>
    简化配置方式,可以采用p这个命名空间。采用p命名空间之后,对于字面值属性,其格式改为:p:属性名="xxx",对于引用对象的属性,其格式为:p:属性名_ref="xxx"

    自动装配:
    bean元素提供了一个指定自动装配类型的属性:autowire="<自动装配类型>"
    byName、byType、constructor、autodetect
    bean的作用域
    bean元素的scope标签指定作用域
    singleton、prototype、requesr、session、globalSession

    基于注解的配置:
    注解定义bean
    @Component
    @Repository、@Service、@Controller这三个特殊类型注解是为了让注解类本身的用途清晰化

    使用注解配置信息启用Spring容器
    使用context命名空间,它提供了通过扫描类名以及应用注解定义Bean的方式
    <?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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <!-- 扫描包以应用注解定义的Bean -->
    <context:component-scan base-package="com.smart"/>

    </beans>

    如果仅希望扫描特定的类而并非基包下所有的类,那么可以使用resource-pattern属性过滤出特有的类,如:
    <context:component-scan base-package="com.smart" resource-pattern="anno/*.class"/>
    这里将基类包设置为com.smart,默认情况下resource-pattern属性的值为**/*.class,即基类包里的所有类
    通过resource-pattern属性仅可以按照自愿名称对基类包中的类进行过滤,但如果仅使用这个,会发现很多时候它并不能满足用户的要求,如仅过滤基类保重实现了XXXService接口的类或者标注了某个特定注解的类等。
    不过这些需求可以很容易通过<context:component-scan-scan>的过滤子元素实现,例如:
    <context:component-scan base-package="com.smart">
    <context:include-filter type="regex" expression="com.smart.anno.*"/>
    <context:exclude-filter type="aspecth" expression="com.smart..*Controller+"/>
    </context:component>
    <context:include-filter>表示要包含的目标类,<context:exclude-filter>表示要排除在外的目标类。这两个过滤元素支持多种类型的过滤表达式:
    类型 示例 说明
    annotation com.smart.XxxAnnotation 所有标注了XxxAnnotation的类。该类型目标类是否标注了某个注解进行过滤
    assignable com.smart.XxxService 所有基层或扩展XxxService的类,盖雷星采用目标类型是否基层或扩展某个特定类名进行过滤
    aspetj com.smart..*Service+ 所有类名以Service结束的类以及基层或扩展它们的类。该类型采用AspectJ表达式进行过滤
    regex com.smart.anno..* 所有com.smart.anno类包下的类。该类型采用正则表达式根据目标类的类名进行过滤
    custom com.smart.XxxTypeFilter 采用XxxTypeFile 通过代码的方式根据过滤规则。该类必须实现org.springframework.core.type.TypeFilter接口

    自动装配Bean
    @AutoWired类型注入 required属性代表如果找不到是否抛异常
    @Autowired(required=false)
    private LogDao logDao;
    @Qualifier 名称注入
    @Qualifier("logDao")
    private LogDao logDao;
    对类成员变量及方法的入参进行标注
    自动将LogDao传给方法入参
    @Autowired
    public void setLogDao(LogDao logDao){
    this.logDao = logDao;
    }
    自动将名为userDao的Bean传给方法入参
    @Autowired
    @Qualifier("userDao")
    public void setUserDao(UserDao userDao){
    this.userDao = userDao;
    }
    如果一个方法拥有多个入参,在默认情况下,Spring自动选择匹配入参类型的Bean进行注入。Spring允许对方法入参标注@Qualifier以注入Bean的名称
    @Autowired
    public void init(@Qualifier("userDao")UserDao userDao, LogDao logDao){
    this.userDao = userDao;
    this.logDao = logDao;
    }
    对集合类型进行标注
    如果对类中集合类的变量或方法入参进行@Autowired标注,那么Spring就会将容器中类型匹配的所有Bean都自动注入进来

    @Autowired
    private List<Plugin> plugins;

    基于java类的配置
    使用java类提供Bean定义信息-JavaConfig子项目
    普通的POJO只要标注@Configuration注解,就可以为Spring容器提供Bean定义的信息。每个标注了@Bean的类方法都相当于提供一个Bean的定义信息
    @Configuration
    public class AopConf{
    @Bean
    public UserDao userDao(){
    return new UserDao;
    }
    @Bean
    public LogDao logDao(){
    return new LogDao();
    }

    @Bean
    public LogonService logonService(){
    LogonService logonService = new LogonService();
    //将前面定义的Bean注入到logonService的Bean中
    logonService.setLogDao(logDao());
    logonService.setUserDao(userDao());
    return logonService;
    }
    }
    @Configuration注解说明这个类可用于为Spring提供Bean的定义信息。类的方法出可以标注@Bean注解,Bean的类型由方法返回值类型决定,名称和方法名相同。也可通过入参显式指定Bean名称,如:@Bean(name="userDao")。直接在@Bean所标注的方法中提供Bean的实例化逻辑。
    如果Bean在多个@Configuration配置类中定义,如何引用不同配置类中定义的Bean呢?
    @Configuration
    public class DaoConfig{
    @Bean
    public UserDao userDao(){
    return new UserDao();
    }
    @Bean
    public LogDao logDao(){
    return new LogDao();
    }
    }
    @Configuration注解类本身已经标注了@Component注解
    @Configuration
    public class ServiceConfig {
    @Autowired
    private DaoConfig daoConfig;

    public LogonService logonService(){
    LogonService logonService = new LogonService();

    logonService.setLogDao(daoConfig.logDao());
    logonService.setUserDao(daoConfig.userDao());
    return logonService;
    }
    }
    直接通过@Configuration类启动spring容器
    Spring提供了一个AnnotationConfigApplicationContext类,能够直接通过标注@Configuration的java类启动Spring容器。
    public class javaConfigTest {
    public static void main(String[] args){
    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConf.class);
    LogonService logonService = ctx.getBean(LogonService.class);
    logonService.printHello();
    }
    }
    ApplicationConfigApplicationContext还支持通过编码的方式加载多个@Configuration配置类,然后通过刷新容器应用这些配置类。
    public class javaConfigTest {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    //注册多个@Configuration配置类
    ctx.register(DaoConfig.class);
    ctx.register(ServiceConfig.class);
    //刷新容器以应用这些注册的配置类
    ctx.refresh();

    LogonService logonServic = ctx.getBean(LogonService.class);
    logonService.printHello();
    }
    用户可以通过代码逐个注册配置类,也可以通过@Import将多个配置类组装到一个配置类中,这样仅仅需要注册这个组装好的配置类就可以启动容器了。

    @Configuration
    @Import(DaoConfig.class)
    public class ServiceConfig {
    @Bean
    public LogonService logonService(){
    LogonService logonService = new LogonService();
    return logonService;
    }
    }
    通过xml配置文件引用@Configuration的配置
    标注了@Configuration的配置类本身相当于一个标注了@Component的类,也是一个Bean,它可以被Spring的<context:component-scan>扫描到。因此,如果希望将配置类组装到XML配置文件中,通过XML配置文件启动Spring容器,仅需要在XML中通过<context:component-scan>扫描到对应的配置即可。
    <context:component-scan base-package="com.smart.conf" resource-pattern="AppConf.class" />

    通过Configuration配置类引用XML配置信息:
    @Configuration配置类中可通过@ImportResource引入XML配置文件,在配置类中即可直接通过@Autowired引用XML配置文件中定义的Bean。

    @Configuration
    @ImportResource("classpath:com/smart/conf/beans2.xml")
    public class LogonAppConfig {
    @Bean
    @Autowired //通过方法入参自动引入userDao和logDo
    public LogonService logonService(UserDao userDao, LogDao logDo) {
    LogonService logonServicve = new LogonService();
    logonService.setUserDao(userDao);
    logonService.setLogDao(logDao);
    return logonServic;
    }

    }

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

    Bean不同配置方式的适用场合
    基于xml配置
    Bean实现类来源于第三方类库
    命名空间的配置只能采用基于xml的配置
    基于注解配置
    Bean的实现类是当前项目开发的,可以直接在java类中适用基于注解的配置
    基于java类配置
    基于java类配置的优势在于可以通过代码方法控制Bean初始化的整体逻辑,所以如果实例化Bean的逻辑比较复杂,则比较适合用基于java类的配置方式
    一般采用XML配置DataSource、SessionFactory等资源Bean,在xml中利用aop、context命名空间进行相关主题的配置。其他所有项目中开发的Bean都通过基于注解配置的方式进行配置。

  • 相关阅读:
    Sonar+IDEA + Maven的集成
    My97DatePicker IE9中,显示全部为1
    Datatable+jeditable+Java 结合使用实现表格的单行刷新
    Datatables表格控件的使用相关网站及遇到的问题
    xss 小练习
    主页面布局 随浏览器大小变化而变化
    使用angular中自定义的directive实现删除确认框
    使用css和js完成模态弹窗功能
    ckplayer插件的使用
    使用JQuery进行表格分页查询
  • 原文地址:https://www.cnblogs.com/aigeileshei/p/7894753.html
Copyright © 2020-2023  润新知