您的位置:首页 > 编程语言 > Java开发

精通Spring 4.x企业应用开发实战——IoC(四)

2018-03-02 16:01 585 查看
Spring容器成功启动条件:
1、相关类包放到程序类路径下;2、为Spring提供完备的Bean配置信息;3、Bean的类放到程序的类路径下了
启动过程:读取程序的Bean配置信息——>在Spring容器中生成Bean配置注册表——>根据注册表实例化Bean,分配好Bean之间的依赖



Bean的素据信息:
1、Bean的实现类;2、Bean的属性信息,如数据源的连接数等;3、Bean的依赖关系;4、Bean的行为配置

Bean:



SpringIoC中一个Bean对应一个<bean>,id为名称,通过getBean()可以获取对应的Bean,不允许出现两个id相同的<bea

依赖注入:属性注入和构造函入

属性注入:通过setXxx()方法注入属性值和依赖对象(最常采用)
public class Car {
private int maxSpeed;
private String brand;
private double price;

public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}

public void setBrand(String brand) {
this.brand = brand;
}

public void setPrice(double price) {
this.price = price;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="car" class="com.smart.DI.Car">
<property name="brand" value="红旗"/>
<property name="maxSpeed" value="200"/>
<property name="price" value="23.6"/>
</bean>
</beans>
配置文件中每个<property>标签在实体类中拥有与其对应的setter方法。
构造函数注入:使用属性注入的前提是Bean中必须提供带参的构造函数
public class Car1 {
private String brand;
private Double price;

public Car1(String brand, double price) {
this.brand = brand;
this.price = price;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 
<bean id="car1" class="com.smart.DI.Car1">
<constructor-arg index="0" value="红旗"/>
<constructor-arg index="1" value="234.45"/>
</bean>
</beans>
配置文件使用了按照索引匹配参数,不过匹配参数从0开始不是1,也可以用按照类型.有时需要两者一起用才能确定。    
<![CDATA[ ]]>处理XML特殊符号,也可以用XML转义字符。

引用其他Bean
Boss类:
package com.smart.DI;

public class Boss {
private Car car;

public void setCar(Car car){
this.car = car;
}

@Override
public String toString() {
return "Boss{" +
"car=" + car +
'}';
}

public void sys(){
System.out.println(toString());
}
}

配置文件:
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="boss" class="com.smart.DI.Boss">
<property name="car" ref="car"/>
</bean>

<bean id="car" class="com.smart.DI.Car"
p:maxSpeed="200"
p:brand="qq"
p:price="123456"
/>
</beans>
测试和结果:
@Test
public void bossCarTest(){
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("BossCar.xml");
Boss boss = (Boss) applicationContext.getBean("boss");
boss.sys();
}


对于上面得类也可以使用内部Bean进行实现:
<bean id="boss" class="com.smart.DI.Boss">
<property name="car">
<bean id="car" class="com.smart.DI.Car"
p:maxSpeed="120"
p:price="123456"
p:brand="wey"
/>
</property>
</bean>


集合类型:
List:
public class Cup {
private List listCup = new ArrayList();
public void setListCup(List listCup) {
this.listCup = listCup;
}
}
<bean id="cup" class="com.smart.DI.Cup">
<property name="listCup">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
</bean>

或者:
<util:list id="list" list-class="java.util.ArrayList">
<value>1</value>
<value>2</value>
<value>3</value>
</util:list>
Set:
<bean id="cup" class="com.smart.DI.Cup">
<property name="listCup">
<set>
<value>1</value>
<value>2</value>
<value>3</value>
</set>
</property>
</bean>
或者:
<util:set id="cup" list-class="java.util.Set">
<value>1</value>
<value>2</value>
<value>3</value>
</util:set>
Map:
private Map map = new HashMap();

public void setMap(Map map) {
this.map = map;
}
<bean id="cupMap" class="com.smart.DI.Cup">
<property name="map">
<map>
<entry>
<key><value>1</value></key>
<value>x</value>
</entry>
</map>
</property>
</bean>

或者:
<util:map id="map" map-class="java.util.HashMap">
<entry key="1" value="x"/>
<entry key="2" value="y"/>
</util:map>

自动装配:其实自动装配就是配置文件少几个ref
类型:
byName:根据名称自动装配;
byType:根据类型进行自动装配
constructor:与byType类似,针对构造函数注入而言
autodetect:根据Bean得自省机制,决定采用byType还是byName进行自动装配。

<beans>元素标签中的default-autowire属性可以配置全局自动装配,默认为no,不开启自动装配,通过ref手动设定。XML配置方式很少启用自动装配功能,而基于注解的配置方式默认采用byType自动装配策略。

lookup方法注入:希望通过一个singleton Bean获取一个prototype Bean时使用。

方法替换:用某个Bean的方法去替换另一个Bean的方法
Bean之间的关系:继承:和Java一样





                            依赖
系统参数类:
public class SystemSettings {
public static int SESSION_TIMEOUT = 30;
public static int REFRESH_CYCLE = 60;
}
SysInit类:修改系统默认参数
public class SysInit {
public SysInit() {
SystemSettings.SESSION_TIMEOUT = 10;
SystemSettings.REFRESH_CYCLE = 100;
}
}
CacheManager类:缓存刷新管理器,根据系统参数REFRESH_CYCLE创建缓存刷新定时任务。
public class CacheManager {
public CacheManager() {
Timer timer = new Timer();
TimerTask cacheTask = new CacheTask();
timer.schedule(cacheTask,0,SystemSettings.REFRESH_CYCLE);
}
}
CacheManager依赖于SystemSettings,而SystemSettings由SysInit负责改变,初始化,CacheManager希望在SysInit加载完成系统参数设置后再启动。
Spring允许用户通过depends-on显示的指定Bean前置依赖的Bean,前置依赖的Bean会在本Bean实例化之前创建好。
<bean id="manager" class="com.smart.DI.CacheManager"
depends-on="sysInit"
/>
<bean id="sysInit" class="com.smart.DI.SysInit"/
                          引用



使用<idref>标签,在容器启动时,Spring负责检查引用关系的正确性,这样可以提前发现错误

Bean的作用域
singleton作用域:默认情况下,Spring的ApplicationContext容器在启动的时候,自动实例化所有的singleton的Bean并缓存在容器中。(调用是同一个实例)
prototype作用域:默认情况下,Spring容器在启动的时候不实例化prototype的Bean(每次新建一个实例)
与Web环境相关的Bean的作用域:
request作用域:request作用域的Bean对应一个HTTP请求和生命周期
session作用域:Bean的作用域横跨整个HTTPSession,当HTTPSession结束后实例才会被销毁。
globalSession作用域:类似于session

FactoryBean
Spring通过反射机制利用<bean>的class属性指定实现类实例化Bean。有时实例化Bean的过程比较复杂,需要在<bean>中提供大量的配置信息。为此,用户可以实现FactoryBean工厂类接口定制实例化Bean的逻辑。
自定义carBeanFactory
public class CarFactoryBean implements BeanFactory{
private String carInfo;

public String getCarInfo() {
return carInfo;
}

//接受逗号分隔的属性设置信息
public void setCarInfo(String carInfo) {
this.carInfo = carInfo;
}

//实例化car Bean
public Car getObject(){
Car car = new Car();
String[] info = carInfo.split(",");
car.setBrand(info[0]);
car.setMaxSpeed(Integer.parseInt(info[1]));
car.setPrice(Double.parseDouble(info[2]));
return car;
}

//返回car的类型
public Class<Car> getObjectType(){
return Car.class;
}
//通过该FactoryBean返回的Bean是singleton
public boolean isSingleton(String s) throws NoSuchBeanDefinitionException {
return false;
}

<bean id="car" class="com.smart.DI.CarFactoryBean"
p:carInfo="红旗,200,123456"
/>

可以通过一次性的为属性设值
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Spring
相关文章推荐