2020年11月28日星期六

Spring Framework02-IOC基本使用

通过上篇文章大概知道ioc、DI的概念了,下面我们详细介绍一下

一、Spring IOC创建对象

IOC通过上文的介绍作用是控制创建对象的解释权,我们把代码重新看一下

//User.javapublic class User { private String username; private String password;   /** 	* 省略有参无参构造器,getter/setter方法 	*/}

我们也不创建dao、service类了,直接就用这个User类来测试

配置文件:applicationContext.

<?
  1. bean的id获取IOC容器中的对象
//测试文件public class MyTest {  ApplicationContext context=new ClassPath

这是IOC创建对象的第一种方式即通过bean的id获取IOC容器中的对象:context.bean("配置文件bean中的id")

还有另外两种方式 :

  1. 通过bean的类型获取对象:context.bean(注入对象的class类型)
 @Test public void test2(){  User user = context.getBean(User.class);  System.out.println(user); }

这种注入方法有劣势,即:配置文件中有多个同类型的bean(即class重复)时,注入对象就会报错,例如:

<?

再接着运行测试文件的时候就会报NoUniqueBeanDefinitionException异常

  1. 通过bean的id和类型获取对象:context.bean("配置文件bean中的id",注入对象的class类型)
 @Test public void test3(){  User user = context.getBean("user",User.class);  System.out.println(user); }

二、SpringDI注入

光创建对象没用,最重要的还是为对象赋值,我们说过DI是IOC的实现,DI更能通过代码体现出来,接下开我们依次介绍几种赋值方式

1、属性注入(即setter注入)

1)简单类型(基本类型+String类型)
 <bean id="user" >  <!-- property:表示属性注入    name:属性的名字,其实是常规bean中set之后的名字(首字母小写)    value:属性值  -->  <property name="username" value="root"></property>  <property name="password" value="123456"></property> </bean>
2)复杂类型(引用类型)
public class Address { private String city;   /** 	* 省略有参无参构造器,getter/setter方法 	*/}public class User { private String username; private String password; private String[] hobby; private Address address; private List list; private Set set; private Map map; private Properties properties;  /** 	* 省略有参无参构造器,getter/setter/toString方法 	*/}
<!-- private String[] hobby -->  <property name="hobby">   <array>    <value>吃饭</value>    <value>看电影</value>    <value>打游戏</value>    <!-- 表示赋空值,可以起占位作用-->    <null></null>   </array>  </property><!--private Address address- 可以有2种注入方式,一种方式在property标签嵌套一个bean--><!--  <property name="address">--><!--   <bean >--><!--    <property name="city" value="大连"></property>--><!--   </bean>--><!--  </property>-->		    <!--ref:引用的bean的id-->  <property name="address" ref="address"></property><!-- private List list-->  <property name="list">   <list>    <value>a</value>    <value>b</value>    <value>c</value>   </list>  </property> <!-- private Set set-->  <property name="set">   <set>    <value>redio</value>    <value>book</value>    <value>game</value>   </set>  </property> <!-- private Map map-->  <property name="map">   <map>    <entry key="1" value="北京"></entry>    <entry key="2" value="上海"></entry>    <entry key="3" value-ref="address"></entry>   </map>  </property> <!-- private Properties properties-->  <property name="properties">   <props>    <prop key="username">root</prop>    <prop key="password">root</prop>   </props>  </property> </bean><bean id="address" >  <property name="city" value="大连"></property> </bean>

List,Set,Map,Properties中还有一种注入方式,即util命名方式,主要的作用:方便别人引用

util命名空间方式
 <!-- private List list-->  <property name="list" ref="mylist"></property> <!-- private Set set-->  <property name="set" ref="myset"></property> <!-- private Map map-->  <property name="map" ref="mymap"></property> <!-- private Properties properties-->  <property name="properties" ref="myproperties"></property> </bean> <util:list id="mylist">  <list>   <value>a</value>   <value>b</value>   <value>c</value>  </list> </util:list> <util:set id="myset">  <set>   <value>redio</value>   <value>book</value>   <value>game</value>  </set> </util:set> <util:map id="mymap">  <entry key="1" value="北京"></entry>  <entry key="2" value="上海"></entry>  <entry key="3" value-ref="address"></entry> </util:map> <util:properties id="myproperties">  <prop key="username">root</prop>  <prop key="password">root</prop> </util:properties>
3)P 命名空间方式

除了上方util命名空间方式之外搭配着还有一个P命名空间

<bean id="user2" p:username="root" p:password="123456" p:address-ref="address" p:list-ref="mylist"></bean>
4)自动注入

可以按照一定规则进行装配注入,不用具体指定为某个属性赋值,在工厂中查找一个bean,为属性注入属性值。

<bean id="address" >  <property name="city" value="上海"></property></bean><bean id="person" autowire="byName"></bean>
  1. byName:按照bean的id进行装配

  2. byType:按照bean的类型来进行注入,但是如果有多个相同类型,就会报错,不知道选择哪一个具体的类型

2、构造器注入

public class User { private String username; private String password; /** 	* 省略有参无参构造器,getter/setter方法 	*/}
 <bean id="user3" >  <!--构造注入的constructor-arg标签里还有几个属性		name:形参列表的名称		value:实参的值		type:参数类型		index:参数索引,从0开始-->  <constructor-arg name="username" value="root"></constructor-arg>  <constructor-arg name="password" value="123456"></constructor-arg> </bean>

属性注入有P命名空间,构造器注入有C命名空间

1)C 命名空间
<bean id="user4" c:username="root" c:password="123456"></bean>
2)自动注入
<bean id="person" autowire="constructor"></bean>
  1. constructor:使用构造器注入,形参列表必须要有对应 bean 对象

三、bean对象之间的关系

1、继承关系

 <bean id="parent" >  <property name="username" value="root"></property> </bean><!--parent:指定继承的bean信息--> <bean id="son" parent="parent"></bean>

2、抽象关系

这个是在继承关系的父bean里添加abstract属性,这个作用就是该bean是否能实例化

 <bean id="parent" abstract="true">  <property name="username" value="root"></property> </bean>

3、依赖关系

这个就是bean的先后创建顺序,depends-on依赖哪个bean就谁先创建谁,然后再创建本对象

<bean id="user5" depends-on="address"></bean><bean id="address" >  <property name="city" value="大连"></property> </bean>

四、bean对象的作用域

通过scope属性指定当前bean的作用域,有四个值

singleton:单例模式,从IOC容器中获取的都是同一个对象,默认的作用域

prototype:多例模式,从IOC容器中获取的对象每次都是新创建

request:每次发送请求都会有一个新的对象

session:每一次会话都会有一个新的对象

<bean id="user5" scope="singleton"></bean>

ps:singleton作用域:每次在创建IOC容器完成之前此对象已经创建完成,即:

ApplicationContext context=new ClassPath

​ prototype作用域:每次是在需要用到此对象的时候才会创建,即

User user = (User) context.getBean("user");

五、工厂对象

静态工厂

工厂本身不需要创建对象,但是可以通过静态方法调用,对象=工厂类.静态工厂方法名();

public class PersonStaticFactory { public static Person getInstance(String name){  Person person=new Person();  person.setId(1001);  person.setAge(18);  person.setName(name);  return person; }}
<!--静态工厂:类名.静态方法()--> <bean id="person" factory-method="getInstance">  <constructor-arg value="jack"></constructor-arg> </bean>
实例工厂

工厂本身需要创建对象,工厂类 工厂对象=new 工厂类;工厂对象.get对象名();

public class PersonInstanceFactory { public Person getInstance(String name){  Person person=new Person();  person.setId(1001);  person.setAge(18);  person.setName(name);  return person; }}
<!--实例工厂:先创建工厂实例,然后调用工厂实例的方法  factory-bean:表示具体工厂类的实例  factory-method:表示具体工厂实例的方法 --><bean id="factory" ></bean> <bean id="person" factory-bean="factory" factory-method="getInstance">  <constructor-arg value="jack"></constructor-arg> </bean>
继承FactoryBean

FactoryBean是Spring规定的一个接口,当前接口的实现类,Spring都会将其作为一个工厂,但是在ioc容器启动的时候不会创建实例,只有在使用的时候才会创建对象

public class MyFactoryBean implements FactoryBean { /**  * 此方式是spring创建bean方式的一种补充,用户可以按照需求创建对象, 创建的对象交由spring IOC容器来进行管理,无论是否是单例,都是在用到的时候才会创建该对象,不用该对象不会创建  */ @Override public Person getObject() throws Exception {		//创建的对象  Person person=new Person();  person.setId(1001);  person.setName("jack");  person.setAge(20);  return person; } @Override public Class<?> getObjectType() {		//返回对象的类型		  return Person.class; } @Override public boolean isSingleton() {			//是否单例  return true; }}
<bean id="factoryBean" ></bean>

六、bean对象的对象的生命周期

创建
  • scope="singleton"(不配置lazy-init="true"属性),每次在创建IOC容器完成之前此对象已经创建完成
  • scope="prototype",每次是在需要用到此对象的时候创建(scope="singleton"配置lazy-init="true"属性也是这样)
初始化

在对象创建完成之后会调用初始化方法

  1. 实现InitializingBean接口

    //实现这个方法,完成初始化操作 @Override public void afterPropertiesSet() throws Exception {  System.out.println("afterPropertiesSet"); }
  2. 对象中提供一个普通的方法同时配置Spring配置文件:

    public void init(){  System.out.println("init");}
    <bean id="p" init-method="init"></bean>

    顺序:对象的注入-》InitializingBean-》普通init-method

销毁
  1. 实现DisposableBean接口
 @Override public void destroy() throws Exception {  System.out.println("destory"); }
  1. 定义一个普通的销毁方法同时配置Spring配置文件
 public void mydestory(){  System.out.println("mydestory"); }
<bean id="p" scope="prototype" init-method="init" destroy-method="mydestory">  <property name="id" value="1001"></property> </bean>

销毁方法只会在scope="singleton"时才会调用,而且需要对象关闭,例如:context.close()

七、配置bean对象初始化方法的前后处理方法

spring中包含一个BeanPostProcessor的接口,可以在bean的初始化方法的前后调用该方法,如果配置了初始化方法的前置和后置处理器,无论是否包含初始化方法,都会进行调用

public class MyBeanPostProcessor implements BeanPostProcessor { //对象初始化之前执行 @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  System.out.println("postProcessBeforeInitialization"+beanName);  return bean; } //对象初始化对象之后运行 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  System.out.println("postProcessAfterInitialization"+beanName);  return bean; }}
 <bean ></bean> <bean id="p" scope="prototype" init-method="init" destroy-method="mydestory">  <property name="id" value="1001"></property> </bean>

八、配置文件参数化

就是把Spring配置文件中需要经常修改的字符串信息,转移到一个更小的配置文件中,方便后期的维护

例如:数据库连接

<context:property-placeholder location="classpath:db.properties"></context:property-placeholder> <bean id="dataSource" >  <property name="username" value="${jdbc.username}"></property>  <property name="password" value="${jdbc.password}"></property>  <property name="url" value="${jdbc.url}"></property>  <property name="driverClassName" value="${jdbc.driverClassName}"></property> </bean>
jdbc.username=rootjdbc.password=rootjdbc.driverClassName=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/demo
//测试@Test public void test11() throws SQLException {  ApplicationContext context=new ClassPath








原文转载:http://www.shaoqun.com/a/493288.html

邮乐网购物商城:https://www.ikjzd.com/w/1776

欧苏丹:https://www.ikjzd.com/w/1756

prime day:https://www.ikjzd.com/w/131


通过上篇文章大概知道ioc、DI的概念了,下面我们详细介绍一下一、SpringIOC创建对象IOC通过上文的介绍作用是控制创建对象的解释权,我们把代码重新看一下//User.javapublicclassUser{privateStringusername;privateStringpassword;/** *省略有参无参构造器,getter/setter方法 */}我们也不创建dao、servi
oklink:oklink
笨鸟海淘:笨鸟海淘
老挝传统保健熏蒸 - :老挝传统保健熏蒸 -
口述:我和小姨子的那些旧事儿:口述:我和小姨子的那些旧事儿
惠东巽寮湾出海捕鱼、海滨温泉一天游:惠东巽寮湾出海捕鱼、海滨温泉一天游

没有评论:

发表评论