350 likes | 556 Views
第 2 章: Spring IOC 容器. 软件技术专业 熊君丽. 2.1 IOC 概述. Inverse of Control,IoC, 是 spring 容器的内核, AOP ,声明式事务都是在此基础上开花结果的。所谓 IOC ,就是通过容器来控制业务对象之间的依赖关系,而非传统的使用代码控制。这也就是反转控制的概念:控制权由应用代码中转到了外部容器,控制权的转移,就是反转。控制权的转移带来的好处是降低了业务对象之间的依赖关系。. 2.2 BeanFactory & ApplicationContext.
E N D
第2章:Spring IOC 容器 软件技术专业 熊君丽
2.1 IOC概述 • Inverse of Control,IoC,是spring容器的内核,AOP,声明式事务都是在此基础上开花结果的。所谓IOC,就是通过容器来控制业务对象之间的依赖关系,而非传统的使用代码控制。这也就是反转控制的概念:控制权由应用代码中转到了外部容器,控制权的转移,就是反转。控制权的转移带来的好处是降低了业务对象之间的依赖关系。 广东科学技术职业学院
2.2 BeanFactory & ApplicationContext • Spring 通过一个配置文件描述bean之间的依赖关系,利用java语言的反射功能实例化bean并建立之间的依赖。 • Bean 工厂是spring框架最核心的接口,它提供了高级Ioc的配置机制。他就是IOC容器,而 ApplicationContext称为应用上下文,有时也被称为spring容器。Spring的应用者面对的是applicationContext. 广东科学技术职业学院
2.2.1 BeanFactory 介绍 • 类的通用工厂,可以创建并管理各种类的对象。POJP,普通的java对象,只要可以被spring容器实例化并管理的java类都可以称为bean。 • 示例2-2-1如下(录像) • 1 创建 car类:属性brand,color,maxSpeed • 2 撰写beans.xml,spring的配置文件 广东科学技术职业学院
Beans.xml • <?xml version="1.0" encoding="UTF-8"?> • -<beans xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"> <bean p:maxSpeed="200" p:brand="红旗CA72" destroy-method="myDestory" init-method="myInit" class="com.smart.Car" id="car"/> • <!-- bean id="car" class="com.smart.beanfactory.Car" init-method="myInit" destroy-method="myDestory" p:brand="红旗CA72"/ --> • </beans> 广东科学技术职业学院
3 获取bean代码如下:演示2-1,2-2(录像) • public class BeanFactoryTest { • public static void main(String[] args) throws Throwable{ • ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); • Resource res = resolver.getResource("classpath:com/smart/beanfactory/beans.xml"); • System.out.println(res.getURL()); • BeanFactory bf = new XmlBeanFactory(res); • System.out.println("init BeanFactory."); • Car car = bf.getBean("car",Car.class); • System.out.println("car bean is ready for use!"); • car.introduce(); • } • } 装载spring配置信息并启动IOC容器 初始化配置文件中定义的Car 广东科学技术职业学院
2.2.2 Application Context ApplicationContext ctx=new FileSystemXmlApplication(“”) 如果不显示指定资源类型前缀,将路径解析成文件系统 在初始化应用上下文时实例化所有实例 Spring支持基于类注解的配置方式,如下例: import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.smart.Car; @Configuration public class Beans { @Bean(name = "car") public Car buildCar() { Car car = new Car(); car.setBrand("红旗CA72"); car.setMaxSpeed(200); return car; } } 演示2-3,2-4 广东科学技术职业学院
类启动器 • publicclass BeanFactoryTest { • /** • * @param args • */ • publicstaticvoid main(String[] args) { • // TODO Auto-generated method stub • /*ResourcePatternResolver resolver=new PathMatchingResourcePatternResolver(); • Resource res=resolver.getResource("classpath:beans.xml"); • BeanFactory bf=new XmlBeanFactory(res);*/ • ApplicationContext ctx=new AnnotationConfigApplicationContext(Beans.class); • Car car=ctx.getBean("car",Car.class); • System.out.println(car.getBrand()); • } • }
WebApplicationContext 该类允许从相对于web根目录的路径中装载配置文件,他的初始化需要ServletContext实例,也就是说它必须在拥有web容器的前提下才能完成启动的工作。 ContextLoaderListener:ContextLoader是一个工具类,用来初始化WebApplicationContext,其主要方法就是initWebApplicationContext, ContextLoader是把WebApplicationContext(XmlWebApplicationContext是默认实现类)放在了ServletContext中,ServletContext也是一个“容器”,也是一个类似Map的结构 。步骤如下: 1配置web.xml文件 (包括监听器+log4j) <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/beans.xml</param-value> </context-param> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>/WEB-INF/log4j.properties</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>log4jConfigServlet</servlet-name> <servlet-class>org.springframework.web.util.Log4jConfigServlet</servlet-class> </servlet> 广东科学技术职业学院
续2-2-2-1 • 2将beans.xml文件放在WEB-INF下 • <bean id="car1" class="com.Car" p:brand="mao" p:color="black" p:maxSpeed="200"/> • 3将web访问放入一个action中 • WebApplicationContext ac2 = WebApplicationContextUtils.getWebApplicationContext(sc); • Car boss=ac2.getBean("car1",Car.class); • System.out.println(boss.getBrand()); • returnSUCCESS; • 4http://localhost:8080/test/user访问 • 演示录像2-2-2-1,源代码见2-2-2-1
2-2-2-1,如果beans.xml文件改成基于java类注解的配置方式,如何修改呢?源文件见2-2-2-1 的web1.xml,另使用Beans.java文件,录像,注解修改2-2-2-1 • <context-param> • <param-name>contextClass</param-name> • <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> • </context-param> • <context-param> • <param-name>log4jConfigLocation</param-name> • <param-value>/WEB-INF/log4j.properties</param-value> • </context-param> • <context-param> • <param-name>contextConfigLocation</param-name> • <param-value>com.Beans</param-value> • </context-param> • <listener> • <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> • </listener> • <servlet> • <servlet-name>log4jConfigServlet</servlet-name> • <servlet-class>org.springframework.web.util.Log4jConfigServlet</servlet-class> • </servlet>
2.2.3资源加载 1 类路径classpath: 2 文件系统file: 3 Web方式:http:// 4 ftp 5 没有前缀:根据ApplicationContext具体实现类采用对象类型的Resource 演示2-2-3(录像)web访问方式 1 将 beans.xml拷贝到web工程的webroot下 2 访问源码: ResourcePatternResolver resolver=new PathMatchingResourcePatternResolver(); Resource res=resolver.getResource("http://localhost:8080/test/beans.xml"); BeanFactory bf=new XmlBeanFactory(res); Car car=bf.getBean("car1",Car.class); System.out.println(car.getBrand()); 广东科学技术职业学院
Ant风格的资源地址 • 支持三种匹配符 • 1 ?:匹配文件名中的任意一个字符 • 2*:匹配文件名中的任意个字符 • 3**:匹配多层路径 • 例子见课本P39
2.3bean装配 Spring容器成功启动的条件: • Spring框架的类都已经放到应用程序的类路径下 • 应用程序为spring提供完备的bean配置信息 • Bean的类都已经放到应用程序的类路径下 • Spring容器高层视图 广东科学技术职业学院
Bean的配置信息 • 1 bean的实现类 • 2 bean的属性信息 • 3 bean的依赖关系 • 4 bean的行为配置 • 讲解P40图2-1spring容器高层视图
2.3.1 bean基本配置 • 装配一个bean • <bean id=“car” class=“com.Car”> Bean名称 Bean类名 广东科学技术职业学院
Bean的命名 1 使用id,注意命名规范 2 使用name,可以使用任意字符,并且可以重复,但后面的bean会覆盖前者。 3 不使用id或者name,spring自动将全限定类名作为bean的名称 广东科学技术职业学院
2.3.2依赖注入 • 属性注入 set,get,演示 • <bean id="car1" class="com.Car"> • <property name="brand"><value>ca23</value></property> • <property name="color"><value>red</value></property> • <property name="maxSpeed"><value>233</value></property> • </bean> • 构造函数注入 • 构造函数注入是除属性注入之外的另一种常用的注入方式,它保证一些必要的属性在bean实例化时就得到设置,并且确保了bean实例在实例化后就可以使用。 • (1)按类型匹配入参。代码2-11,演示2-11
(2)按索引入参,演示 • <bean id="car1" class="com.Car"> • <constructor-arg index="0" value="ca"/> • <constructor-arg index="1" value="red"/> • <constructor-arg index="2" value="34"/> • </bean> • (3)按类型匹配和索引入参 • (4)通过自身反射类型匹配入参 • <bean id="boss" class="com.Boss"> • <constructor-arg ><value>ming</value></constructor-arg> • <constructor-arg ><ref bean="car1"/></constructor-arg> • </bean> • 总结:指定类型和索引入参不失为一个好习惯
循环依赖问题 • 当两个bean都采用构造函数注入,而且都通过构造函数入参引用对方,就会发生类似线程死锁的循环依赖问题。 • P47 演示 • 总结:解决这个问题,将构造函数注入方式调整为属性注入方式即可。
2.3.3注入参数详解 • Spring配置文件中,用户可以使用简单类型,也可以使用集合复杂数据类型,还可以注入其他bean。 • 简单类型:代码P48:2-15 • 引用其他bean:ref元素 • Bean:可以引用同一容器或父容器的bean • Local:只能引用同一容器的bean • Parent:引用父容器的bean,示例2-3-3,源码2-3-3
集合类型: • (1)list 演示 源码2-3-3-1 • 拓展练习:(2)Map (3)properties
(4) util命名空间配置集合类型:配置一个集合类型的bean 示例2-3-3-3 • 步骤1:配置spring文件 • <beans • xmlns="http://www.springframework.org/schema/beans" • xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" • xmlns:util="http://www.springframework.org/schema/util" • xmlns:p="http://www.springframework.org/schema/p" • xsi:schemaLocation="http://www.springframework.org/schema/beans • http://www.springframework.org/schema/beans/spring-beans-3.0.xsd • http://www.springframework.org/schema/util • http://www.springframework.org/schema/util/spring-util-3.1.xsd"> • <util:list id="fav1" list-class="java.util.LinkedList"> • <value>read</value> • <value>play</value> • </util:list><beans>
步骤2:访问 • LinkedList l=bf2.getBean("fav1",java.util.LinkedList.class); • Iterator it=l.iterator(); • while(it.hasNext()) • System.out.println(it.next());
简化配置方式 • <p>命名空间,添加xmlns:p=“” • 演示并访问P52 代码2-17 • P:属性名=“” • P:属性名-ref=“” • 自动装配(不建议使用) • Spring容器可以按照规则对容器中的bean进行自动装配。类型如下:byName,byType,constructor,autodetect
2.3.4 • Bean作用域: • Scope=“” • P54五种选择:singleton,prototype,request,session,globalSession
2.3.5基于注解的配置 • 1 使用注解定义bean:合并bean的定义信息和实现类 • @component(“car”) • @repository用于对dao实现类进行注解 • @service用于对service实现类进行注解 • @controller用于对controller实现类进行注解 • 2 使用注解配置信息启动spring容器:context命名空间P55,它提供了通过扫描类包以应用注解定义bean的方式,spring容器将会扫描这个基类包里的所有类。 • Component-scan:base-package指定一个需要扫描的基类包,reource-pattern属性过滤出特定的类,演示录像
自动装配bean • Spring通过@autowired注解实现bean的依赖注入 • @service • Public class LogonService • {@autowired • Private logDao logDao; • @autowired(required=false) • @qualifier(“userDao”) • Private UserDao userDao; • } 定义一个service 分别注入Logdao及userdao的bean Spring容器找不到bean时不抛出异常 限定bean的名称
2.3.6基于java类的配置javaConfig • 使用java类提供bean定义信息 • 2-21 • @configuration • @bean • 不同类中引用bean,只需使用,拓展练习 • @autowired • 如果使用 • @scope(“prototype”),则每次调用返回一个新的bean
直接通过@configuration类启动spring容器,例子2-3-6,演示直接通过@configuration类启动spring容器,例子2-3-6,演示 • @Configuration • publicclass BeanFactoryTest { • @Bean • public Car car() • {returnnew Car();} • @Bean • public Boss boss() • { • Boss boss=new Boss(); • boss.setCar(car()); • return boss; • } • publicstaticvoid main(String[] args) { • ApplicationContext ac2 = new AnnotationConfigApplicationContext(BeanFactoryTest.class); • Boss b=ac2.getBean(Boss.class); • System.out.print(b.getCar().getBrand()); • } • }
引用不同配置类中定义的bean,例子2-3-6-1,演示引用不同配置类中定义的bean,例子2-3-6-1,演示 • 1 CarConfig中定义 car • @Configuration • publicclass AppTest { • @Bean • public Car car() • {returnnew Car();} • } • 2 BossConfig中定义Boss,boss使用 1 中定义的 car • @Configuration • @Import(AppTest.class) • publicclass Logon { • @Autowired • private AppTest apptest; • @Bean • public Boss boss() • { Boss boss=new Boss(); • boss.setCar(apptest.car()); • return boss;} • } • 3 调用 2中定义的boss,显示 car的信息。
多编码方式加载多个配置类 • AnnotationConfigApplicationContext ac2 = new AnnotationConfigApplicationContext(); • ac2.register(AppTest.class); • ac2.register(Logon.class); • ac2.refresh(); • Boss boss=ac2.getBean(Boss.class); • Car car=ac2.getBean(Car.class); • System.out.print(car.getBrand()); • 或者@Import()组装到一个类中
通过xml配置文件引用@configuration的配置2-28 • <context:component-scan> 通过configuration配置类引用xml配置信息 • @importResource(“classpath:com/smart/conf/beans2.xml”) • @autowired
2.3.7不同配置方式的比较 • 基于xml配置:DataSource,SessionFactory,无法在类中标注注解;命名空间的配置 • 基于注解配置:bean的实现类是当前项目开发的,可以直接在java类中使用基于注解的配置 • 基于java类配置:可以通过代码方式控制bean初始化的整体逻辑,通常适合实例化逻辑较为复杂的bean。