前言
记录学习经历,前接第一步
Spring核心机制的依赖注入,改变传统的编程习惯,对组件的实例化交由Spring容器完成,需要时注入应用程序,从而将组件之间的依赖关系进行解耦,关键在与配置文件xml中的bean元素
ApplicationContext
Spring IoC设计核心是Bean容器,BeanFactory采用Java的工厂模式,通过从xml配置文件中读取JavaBean的定义来实现JavaBean的创建、配置和管理
ApplicationContext扩展了BeanFactory容器,继承BeanFactory接口,ApplicationContext接口有3个常用的实现类
(1)ClassPathXmlApplicationContext
从类地址ClassPath中寻找xml配置文件,找到并装载ApplicationContext的实例化工作
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml ");
(2)FileSystemXmlApplicationContext
从指定的文件系统路径中寻找指定的xml配置文件,找到并装载ApplicationContext的实例化工作
classes目录:
ApplicationContext ctx=new FileSystemXmlApplicationContext("classpath:applicationContext.xml")
相对路径
ApplicationContext ctx=new FileSystemXmlApplicationContext("src\\applicationContext.xml");
绝对路径
ApplicationContext ctx=new FileSystemXmlApplicationContext("C:\\TomCat\\apache-tomcat-9.0.22\\webapps\\sy8\\src\\applicationContext.xml");
与ClassPathXmlApplicationContext的区别在与FileSystemXmlApplicationContext通过参数指定配置文件的位置读取配置文件,可以获取类路径外的资源
(3)XmlWebApplicationContext
从Web应用中寻找指定的xml配置文件,找到并装载完成ApplicationContext的实例化工作
Web项目
在Java项目中通过上述3个类手工实例化ApplicationContext容器,但对于Web项目不行,Web项目的启动是由相应的Web服务器负责,在Web项目中的ApplicationContext容器的实例化工作最好交给Web服务器来完成,Spring提供了两种方法:
(1)基于contextLoaderListener实现(适用于Servlet2.4及以上)
在xml中:
<!--指定Spring配置文件的位置,多个配置文件以逗号分隔-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--指定以listener方式启动Spring容器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
(2)基于ContextLoaderServlet实现
在web.xml中:
<!--指定Spring配置文件的位置,多个配置文件以逗号分隔-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--以servlet方式启动Spring容器-->
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
</servlet>
Bean的作用域
容器最重要的任务是创建并管理JavaBean的生命周期
Bean的作用域就是Bean实例的生存空间或有效范围
Spring为Bean实例定义了5种作用域来满足不同情况
- singleton(单实例作用域):在每个Spring IoC容器中,一个bean定义对应一个对象实例
- prototype(原型模式作用域):一个bean定义对应多个对象实例
- request:在一次http请求中,容器会返回该Bean的同一个实例,对于不同的http session请求,会返回不同的实例
- session:在一次http session中,容器会返回该Bean的同一个实例,对于不同的http session请求会返回不同实例
- global session:在一个全局的http session中,容器会返回该Bean的同一个实例
request,session、global session仅在基于Web的应用中使用
当用户使用Spring的WebApplicationContext时,可以使用request,session、global session
(1)singleton
Spring IoC容器只会存在一个共享的bean实例
applicationContext.xml
<bean id="helloworld" class="com.HelloWorld" scope="singleton">
<property name="userName" value="zhangsan"></property>
</bean>
测试类
package com.show;
import com.HelloWorld;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestHelloWorld {
public static void main(String [] args){
//加载xml配置
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
//获得配置中的实例
HelloWorld helloWorld=(HelloWorld)ctx.getBean("helloworld");
HelloWorld helloWorld1=(HelloWorld)ctx.getBean("helloworld");
System.out.println(helloWorld==helloWorld1);
//调用方法
helloWorld.show();
}
}
(2)prototype
每次对该bean请求时都会创建一个新的bean实例
将上面的xml中scope改为prototype
<bean id="helloworld" class="com.HelloWorld" scope="prototype">
<property name="userName" value="zhangsan"></property>
</bean>
测试类结果:
基于Annotation(注解)的Bean装配
当应用中Bean过多,xml配置显得臃肿,jdk5开始提供Annotation注解的功能
Spring定义的Annotation注解
- @ Component注解
泛化的概念,表示一个组件(Bean),可以作用在任何层次 - @Repository注解
用于数据访问层(DAO层)的类识别为Spring的Bean - @Service注解
用于业务层,目前与@Component功能相同 - @Controller
标识表示层组件,目前和Component功能相同
使用 @ Component、@Repository、@Service、@Controller注解,Spring会自动创建相应的BeanDefinition对象,并注册到ApplicationContext中,这些类就成为了Spring的受管组件
- @Autowired注解
用于对Bean的属性变量、属性的set方法及构造函数进行标注,配合对应的注解处理器变成Bean的自动配置工作 - @Resource注解
相当于@Autowired,配置对应的注解处理器完成Bean的自动配置工作,区别在与 @Autowired默认安装Bean类型进行装配, @Resource默认按照Bean实例名进行装配,@Resource包括name、type两个重要属性,Spring将name属性解析为Bean实例的名称,将type解析为Bean实例的类型 - @Qualifier注解
与@Autowired注解配合,将默认按Bean类型进行装配修改为按Bean实例名称进行装配,Bean的实例名称由@Qualifier注解的参数指定
实例理解(第一步的登录系统)
(1)修改UserDao接口的实现类UserDaoImpl
使用@Repository注解,将数据访问层的类UserDaoImpl标识为Spring Bean,通过value属性标识该Bean的名称为userDao
import com.Dao.UserDao;
import org.springframework.stereotype.Repository;
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public boolean login(String loginName, String loginPwd) {
if (loginName.equals("admin")&&loginPwd.equals("123456")){
return true;
}
else return false;
}
}
(2)修改UserService接口的实现类UserServiceImpl
@Service注释将业务逻辑层的类UserServiceImpl标识为Spring Bean,名称为userService
在UserDAO类型的属性userDAO的Bean使用@Autowired注解,将步骤1Spring容器实例化的名称为userDao的Bean装配到属性userDao
package com.Dao.Impl;
import com.Dao.Service.UserService;
import com.Dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
UserDao userDao;
public void setUserDao(UserDao userDao){
this.userDao=userDao;
}
@Override
public boolean login(String loginName, String loginPwd) {
return userDao.login(loginName,loginPwd);
}
}
(3)修改xml配置文件
xml文件没有了bean元素,需要在Spring配置文件中启动Bean的自动扫描功能,Spring容器会扫描这个基包中及其子包中的所有类
<?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:component-scan base-package="com"></context:component-scan>
</beans>
(4)运行测试程序TestLogin
注释使xml配置文件不再臃肿,从而向“零配置”迈进