Bootstrap

spring基本概念 环境搭建 IOC的XML方式使用 IOC的自动装配 IOC的延迟加载 Autowired

Spring介绍

了解Spring的基本概念
掌握Spring的环境搭建
掌握IOC的XML方式使用
掌握IOC的自动装配
掌握IOC的延迟加载

1.了解Spring的基本概念

Spring 是一个开源框架,Spring 是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson在其著作 Expert One-On-One J2EE Development and Design 中阐述的部分理念和原型衍生而来。
它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE应用程序开发提供集成的框架。Spring 使用基本的 JavaBean 来完成以前只可能由 EJB 完成的事情。然而,Spring 的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何 Java 应用都可以从 Spring 中受益。Spring 的核心是控制反转(IOC)和面向切面(AOP)。简单来说,Spring 是一个分层的 轻量级开源框架。
IOC把创建对象的工作交由spring完成,Spring在创建对象的过程中可以完成对象的属性赋值(DI)
DI依赖注入

掌握Spring的环境搭建

在这里插入图片描述
2.1、创建java项目导入相应jar包
在这里插入图片描述
2.2、创建配置文件
配置文件的名字可以任意设置,建议设置为applicationContext.xml,所以这里我们创建一个名为applicationContext.xml的配置文件

<?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">
 
</beans>

2.3、添加相应模块
在项目中添加dao、model、service层代码
2.4、将bean的实例化交给Spring

<bean name="userDao" class="com.tledu.dao.impl.UserDaoImpl" />
<!--name 属性名字/ref 引用的bean的名字-->
<bean id="userService" class="com.tledu.service.UserService">
	<property name="userDao"  ref="userDao" />
</bean>

2.5、测试类

public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserServiceImpl userServiceImpl = context.getBean("userService", UserServiceImpl.class);
    User user = userServiceImpl.getUserById(1);
    System.out.println(user);
}

3. 两种注入

通过构造方法注入

 <bean name="userDao" class="com.tledu.dao.impl.UserDaoImpl" />
 <bean id="userService" class="com.tledu.service.UserService">
        <constructor-arg ref="userDao"/>
 </bean>

普通属性注入
上面我们注入的是关联对象,比如 int的值如何注入呢

<bean name="userDao" class="com.tledu.dao.impl.UserDaoImpl">
<!-- 如果不是指向对象,直接用value设置值就行 -->
	<property name="daoId" value="82"></property>
	<property name="daoStatus" value="good"></property>
</bean>

4.scope

简单说就是对象在spring容器(IOC容器)中的生命周期
目前,scope的取值有5种取值:
在Spring 2.0之前,有singleton和prototype两种;
在Spring 2.0之后,为支持web应用的ApplicationContext,增强另外三种:request,session和global session类型,它们只实用于web程序,通常是和XmlWebApplicationContext共同使用

singleton

此取值时表明容器中创建时只存在一个实例,所有引用此bean都是单一实例。
也就是说创建对象是单例模式,并且如果不进行设置,默认就是单例

prototype

简单来说,就是每次获取都创建一个新对象,并且这个对象的生命周期不归Spring管理

配置scope方式

<bean name="userDao" class="com.tledu.dao.impl.UserDaoImpl">
  <!-- 如果不是指向对象,直接用value设置值就行 -->
  <property name="daoId" value="82"></property>
  <property name="daoStatus" value="good"></property>
	</bean >
	<!-- scope 
               singleton : 单例 只创建一个,默认就是 
		   prototype : 每一次getBean 都会创建一个新的实例化对象  
               request,session : 需要特殊环境支持 -->
	<bean id="userService" class="com.tledu.service.UserService"
  scope="singleton">
  <!-- 构造方法注入 -->
  <constructor-arg>
  	<ref bean="userDao" />
  </constructor-arg>
</bean>

7、集合属性

7.1、相关类
UserDaoImpl中提供对应的变量

	private List<String> lists;
	private Set<String> sets;
	private Map<String, String> maps;
	public List<String> getLists() {
  		return lists;
	}
	public void setLists(List<String> lists) {
  		this.lists = lists;
	}
	public Set<String> getSets() {
 		 return sets;
	}
	public void setSets(Set<String> sets) {
 		 this.sets = sets;
	}
	public Map<String, String> getMaps() {
 		 return maps;
	}
	public void setMaps(Map<String, String> maps) {
 		 this.maps = maps;
	}

7.2、配置文件

<bean name="userDao" class="com.tledu.dao.impl.UserDaoImpl">
  <property name="lists" >
  	<list>
    	<value>1</value>
    	<value>2</value>
  	</list>
  </property>
  <property name="sets" >
  <!-- set不可重复,重复不添加,所以只有第一个三 -->
  	<set>
    	<value>3</value>
    	<value>3</value>
    	<value>5</value>
    	<value>4</value>
  	</set>
  </property>
  <property name="maps">
  <!-- mapkey不可重复,重复key不添加,value覆盖 -->
  	<map>
    	<entry key="1"  value="2"></entry>
    	<entry key="1"  value="3"></entry>
    	<entry key="2"  value="2"></entry>
  	</map>
  </property>
	</bean>

	<bean id="userService" class="com.tledu.zrz.service.UserService"
  scope="singleton">
  <!-- 构造方法注入 -->
  <constructor-arg>
  	<ref bean="userDao" />
  </constructor-arg>
	</bean>

7.3 测试

8、自动装配

两种注入方式
1 set方法注入

<property name="userDao" ref="userDao" />

2 构造方法注入

<constructor-arg>
    <ref bean="userDao"/>
</constructor-arg>

Autowire : 自动装配,两种取值
1 byName
2 byType

8.1、byName

byName是根据setter方法名字进行匹配,如果找不到,就不赋值
如 setUserDao 方法  就会找userDao,如果 bean的ID为 UserDao 也一样找不到,区分大小写
设置方式
<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl">
</bean>
<bean id="userService" class="com.tledu.zrz.service.UserService"  
 autowire="byName">
</bean>

8.2、byType

byType是根据setter方法的参数列表中的数据类型进行匹配,如果beans.xml中出现了多个相同类型的对象,就会报错
如 setUserDao(UserDao userDao) 方法  就会找UserDao,如果是接口,就找对应的实现类对象
设置方式
<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl">
</bean>
<bean id="userService" class="com.tledu.zrz.service.UserService"  
 autowire="byType">
</bean>
注意 : 使用自动装配,需要有公共的无参构造,虽然这里就算是私有化构造方法也依然可以创建对象,但是还是提供一个公共的比较好,万一别的框架需要呢

8.2、constructor

可以根据构造函数进行依赖的注入。
<bean name="userService" class="com.tledu.service.impl.UserServiceImpl" >
    <!--<property name="userDao" ref="userDao" />-->
   <!-- <constructor-arg name="userDao" ref="userDao" />-->
    <constructor-arg>
        <ref bean="userDaooo"></ref>
    </constructor-arg>
</bean>

9、生命周期和迟加载

之前servlet的生命周期
构造方法 -- init -- service -- destroy  
那么spring创建对象的生命周期呢?
Spring中是没有init、service和destroy的,但是我们可以指定某个方法在创建完对象之后执行,某个方法在最后销毁的时候执行.

9.1、生命周期

9.1.1、相关类

UserService中提供对应的方法
public void init(){
  System.out.println("init--------");
	}
	public void destroy(){
  System.out.println("destroy----------");
	}
	public UserService() {
  System.out.println("service构造方法");
}

9.1.2、配置文件

<bean name="userDao" class="com.tledu.dao.impl.UserDaoImpl" >
	</bean>
	<!--  
  init-method : 用于设置初始化的方法
  destory-method : 用于设置销毁资源的方法
  -->
	<bean id="userService" class="com.tledu.service.UserService"  
  autowire="byName"   init-method="init" destroy-method="destroy"  >
	</bean>

9.1.3、测试

@Test
public void testAdd() {
  ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
    "beans.xml");
  // userService是bean的id或name
   UserService userService = (UserService) applicationContext
   .getBean("userService");
  // // userService.add(null);
   System.out.println(userService.getUserDao());
  // 销毁Spring容器
   applicationContext.destroy();
}

Destroy之所以会执行,是因为我们默认创建对象的时候是单例模式
这个时候对象的生命周期会和Spring容器的生命周期绑定到一起,所以当我们销毁Spring容器的时候,会把所有的对象销毁,并自动调用destroy方法
但是如果我们把scope设置为prototype的时候,对象的生命周期就不会再和Spring容器绑定,销毁Spring容器的时候也就不会再执行该对象的destroy方法
比如

<bean name="userDao" class="com.tledu.dao.impl.UserDaoImpl" >
	</bean>
	<!--  
  init-method : 用于设置初始化的方法
  destory-method : 用于设置销毁资源的方法
  -->
	<bean id="userService" class="com.tledu.zrz.service.UserService"  scope="prototype"
  autowire="byName"   init-method="init" destroy-method="destroy"  >
</bean>

9.2、迟加载
Spring容器默认是在执行
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(“beans.xml”);
进行解析的时候创建对象并调用init,
如果我们不想让某个类在解析的时候就创建对象,而是用到的时候在创建对象的话,就需要设置迟加载比如想要对userService迟加载可以这样设置

9.2.1、相关类
在UserDaoImpl和UserService中的构造方法添加输出语句进行测试
public UserDaoImpl(){
System.out.println(“Dao构造方法”);
}
public UserService() {
System.out.println(“service构造方法”);
}
9.2.2、配置文件

<bean name="userDao" class="com.tledu.dao.impl.UserDaoImpl" >
<bean id="userService" class="com.tledu.service.UserService"  scope="prototype"
  	autowire="byName"   init-method="init" destroy-method="destroy" lazy-init="true"  >
</bean>

9.2.3、测试

@Test
public void testAdd() {
  ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
    "beans.xml");
}

结果

通过结果可以看出,UserService的对象没有创建,那么什么时候创建呢?
UserService userService = (UserService) applicationContext.getBean(“userService”);
当调用getBean()的时候 创建
或者是使用到这个对象的时候,比如我们获取userService对象,但是需要将userDao对象注入到userService中,那么这时候就算没有通过getBean(“userDao”) 而是通过getBean(“userService”) 也会创建userDao对象,因为在UserService中用到userDao了

为了使用方便,Spring还提出了default-lazy-init=“true”
比如我们通过xml创建了10个对象,这10个对象都需要迟加载,那么每个bean标签中都设置lazr-init是比较麻烦的
于是我们可以在beans标签中添加default-lazy-init=“true” 对所有的bean进行迟加载
default-lazy-init 和 lazy-init 可以同时存在,比如 10个对象中 只有一个不需要迟加载,那么可以使用 default-lazy-init = true 全部设置迟加载,然后再去指定的bean中添加 lazy-init=false 就可以

<?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"  default-lazy-init="true" >

10. Autowired

1.2.1.1 创建项目并导包
和昨天的步骤一样,不过需要引入一个新的jar包spring-aop-4.2.1.RELEASE.jar
在这里插入图片描述
1.2.1.3 开启注解的支持

<?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.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
	<!-- 引入注解约束 -->
	<!-- 使用注解形式自动装配 -->
	<context:annotation-config />
</beans>

1.2.1.2 业务类
业务类内容不变,只是要多加几个注解

public class UserService {
    private IUserDao userDao;

    @Autowired
    public void setUserDao(IUserDao userDao) {
        this.userDao = userDao;
    }
}

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;