一、Spring IOC手动注入(装配)
1.set方法注入(掌握)
1.1属性字段提供set方法
public class UserService {
/*set手动注入*/
//注入UserDao 提供set方法
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
//注入SxtStudent
private SxtStudent sxtStudent;
public void setSxtStudent(SxtStudent sxtStudent) {
this.sxtStudent = sxtStudent;
}
//常对象String 注入set
private String str;
public void setStr(String str) {
this.str = str;
}
//基本类型 Integer
private Integer id;
public void setId(Integer id) {
this.id = id;
}
//list集合
private List<String> list;
public void setList(List<String> list) {
this.list = list;
}
//遍历list的值
public void printList(){
list.forEach(s -> System.out.println(s));
}
//set集合注入
private Set<String> set;
public void setSet(Set<String> set) {
this.set = set;
}
//遍历set集合
public void printSet(){
set.forEach(s -> {
System.out.println(s);
});
}
//map
private Map<String,String> map;
public void setMap(Map<String, String> map) {
this.map = map;
}
//遍历map
public void printMap(){
map.forEach((k,v)->{
System.out.println(k+","+v);
});
}
// Properties set注入(提供set方法)
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
// Properties输出
public void printProperties(){
properties.forEach((k,v) -> System.out.println(k + ","+ v ));
}
public void test(){
System.out.println("UserService test.......");
//调用userDao
userDao.test();
//调用sxtStudent
sxtStudent.test();
//调用对象String
System.out.println("str:"+str);
//基本类型 Integer
System.out.println("编号:"+id);
//list集合
printList();
//set集合
printSet();
//map集合
printMap();
//properties
printProperties();
}
}
1.2配置文件的bean标签设置property标签
<?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="userService" class="com.shsxt.service.UserService">
<!--bean对象注入-->
<property name="userDao" ref="userDao"/>
<property name="sxtStudent" ref="sxtStudent"/>
<!--常用对象注入-->
<property name="str" value="Hello Spring"/>
<!--基本类型注入-->
<property name="id" value="100"/>
<!--list集合注入-->
<property name="list">
<list>
<value>江西</value>
<value>上海</value>
<value>浙江</value>
</list>
</property>
<!--set集合注入-->
<property name="set">
<set>
<value>南昌</value>
<value>浦东区</value>
<value>杭州</value>
</set>
</property>
<!--map注入-->
<property name="map">
<map>
<entry>
<key><value>邓紫棋</value></key>
<value>平凡天使</value>
</entry>
<entry>
<key><value>花花</value></key>
<value>我们</value>
</entry>
<entry>
<key><value>易烊千玺</value></key>
<value>朋友请听好</value>
</entry>
</map>
</property>
<!--Properties注入-->
<property name="properties">
<props>
<prop key="1">歌手</prop>
<prop key="2">演员</prop>
<prop key="3">舞蹈</prop>
</props>
</property>
</bean>
<bean id="userDao" class="com.shsxt.dao.UserDao"></bean>
<bean id="sxtStudent" class="com.shsxt.dao.SxtStudent"></bean>
</beans>
1.3加载资源
public class Test01 {
public static void main(String[] args) {
//获取上下文
BeanFactory factory=new ClassPathXmlApplicationContext("spring.xml");
//通过getBean获得实例化好的对象
UserService userService= (UserService) factory.getBean("userService");
//调用方法
userService.test();
}
}
2.构造器注入
2.1提供带参构造器
public class UserService02 {
/*构造器注入*/
private UserDao02 userDao02;
private SxtStudent02 sxtStudent02;
private String name;
public UserService02(UserDao02 userDao02) {
this.userDao02 = userDao02;
}
public UserService02(UserDao02 userDao02, SxtStudent02 sxtStudent02) {
this.userDao02 = userDao02;
this.sxtStudent02 = sxtStudent02;
}
public UserService02(UserDao02 userDao02, SxtStudent02 sxtStudent02, String name) {
this.userDao02 = userDao02;
this.sxtStudent02 = sxtStudent02;
this.name = name;
}
public void test(){
System.out.println("UserService02 test......");
userDao02.test();
sxtStudent02.test();
System.out.println("名字:"+name);
}
}
2.2XML配置
<?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="userService02" class="com.shsxt.service.UserService02">
<constructor-arg name="userDao02" ref="userDao02"/>
<constructor-arg name="sxtStudent02" ref="sxtStudent02"/>
<constructor-arg name="name" value="张三"/>
</bean>
<bean id="userDao02" class="com.shsxt.dao.UserDao02"></bean>
<bean id="sxtStudent02" class="com.shsxt.dao.SxtStudent02"></bean>
</beans>
2.3加载资源
public class Test02 {
public static void main(String[] args) {
//获取上下文
BeanFactory factory=new ClassPathXmlApplicationContext("spring02.xml");
//通过getBean获得实例化好的对象
UserService02 userService02= (UserService02) factory.getBean("userService02");
//调用方法
userService02.test();
}
}
构造器可能出现的问题:循环依赖
带参构造器
public class AccountService {
private RoleService roleService;
public AccountService(RoleService roleService) {
this.roleService = roleService;
}
public void test() {
System.out.println("AccountService Test...");
}
}
public class RoleService {
private AccountService accountService;
public RoleService(AccountService accountService) {
this.accountService = accountService;
}
public void test() {
System.out.println("RoleService Test...");
}
}
xml配置
<!--
如果多个bean对象中互相注入,则会出现循环依赖的问题
可以通过set方法注入解决
-->
<bean id="accountService" class="com.shsxt.service.AccountService">
<constructor-arg name="roleService" ref="roleService"/>
</bean>
<bean id="roleService" class="com.shsxt.service.RoleService">
<constructor-arg name="accountService" ref="accountService"/>
</bean>
如何解决:将构造器注入改为set方法注入
public class AccountService {
private RoleService roleService;
/* public AccountService(RoleService roleService) {
this.roleService = roleService;
}*/
public void setRoleService(RoleService roleService) {
this.roleService = roleService;
}
public void test() {
System.out.println("AccountService Test...");
}
}
public class RoleService {
private AccountService accountService;
/* public RoleService(AccountService accountService) {
this.accountService = accountService;
}*/
public void setAccountService(AccountService accountService) {
this.accountService = accountService;
}
public void test() {
System.out.println("RoleService Test...");
}
}
xml配置
<!--修改为set方法注入-->
<bean id="accountService" class="com.shsxt.service.AccountService">
<property name="roleService" ref="roleService"/>
</bean>
<bean id="roleService" class="com.shsxt.service.RoleService">
<property name="accountService" ref="accountService"/>
</bean>
3.静态工厂注入(了解)
3.1定义工厂类
public class StaticFactory {
//定义静态方法
public static Car createCar(){
return new Car();
}
}
3.2在配置文件中设置bean标签,指定工厂对象并设置对应的方法
<!--静态工厂注入-->
<bean id="car" class="com.shsxt.factory.StaticFactory" factory-method="createCar"></bean>
3.3加载资源
public class Test04 {
public static void main(String[] args) {
BeanFactory factory=new ClassPathXmlApplicationContext("spring03.xml");
Car car = (Car) factory.getBean("car");
car.test();
}
}
4.实例化工厂注入(了解)
4.1定义工厂类
public class InstanceFactory {
public Car create(){
return new Car();
}
}
4.2声明工厂bean标签,声明bean对象,指明工厂对象和工厂方法
<!--实例化工厂注入-->
<bean id="instanceFactory" class="com.shsxt.factory.InstanceFactory"></bean>
<bean id="car" factory-bean="instanceFactory" factory-method="create"></bean>
4.3加载资源
public class Test04 {
public static void main(String[] args) {
BeanFactory factory=new ClassPathXmlApplicationContext("spring03.xml");
Car car = (Car) factory.getBean("car");
car.test();
}
}
二、Spring IOC自动注入(装配)
1.准备环境(修改配置文件)
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<beans>
2.开启自动化注入
<!--开启自动化装配(注入)-->
<context:annotation-config/>
<bean id="userService" class="com.shsxt.service.UserService"></bean>
3.给注入的bean对象添加注解
@Resource注解
@Resource注解实现自动注入(反射)
1、默认根据属性字段名称查找对应的bean对象 (属性字段的名称与bean标签的id属性值相等)
2、如果属性字段名称未找到,则会通过类型(Class类型)查找
3、属性可以提供set方法,也可以不提供set方法
4、注解可以声明在属性级别 或 set方法级别
5、@Resource可以设置name属性,name属性值必须与bean的id属性值一致;如果设置了name属性值,就只会按照name属性值查找bean对象
6、当注入接口时,如果接口只有一个实现则正常实例化;如果接口存在多个实现,则需要使用name属性指定需要被实例化的bean对象
public class UserService {
//自动注入
@Resource
private UserDao userDao;
//自动注入
//@Resource(name="userDao")
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}*/
public void test(){
System.out.println("UserService test.......");
userDao.test();
}
}
加载资源
public class Test01 {
public static void main(String[] args) {
BeanFactory factory=new ClassPathXmlApplicationContext("spring.xml");
UserService userService= (UserService) factory.getBean("userService");
userService.test();
}
}
@AutoWired注解
@Autowired注解实现自动化注入:
1、默认通过类型(Class类型)查找bean对象 与属性字段的名称无关
2、属性可以提供set方法,也可以不提供set方法
3、注解可以声明在属性级别 或 set方法级别
4、可以添加@Qualifier结合使用,通过value属性值查找beam对象(value属性值必须要设置,且值要与bwan标签的id属性值对应)
@Autowired
@Qualifier(value = "accountDao")
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
三、Spring IOC扫描器
过程
Spring IOC扫描器
作用:bean对象统一进行管理,简化开发配置,提高开发效率
1、设置自动化扫描的范围
如果bean对象未在指定包范围,即使声明另外注解,也无法实例化
2、使用指定的注解(声明在类级别) bean对象的id属性默认是 类的首字母小写
Dao层:
@Repository
Service层:
@Service
Controller层:
@Controller
任意类:
@Component
注:开发过程中建议按照指定规则声明注解
1.设置自动化扫描的范围
<!--设置自动化扫描的范围-->
<context:component-scan base-package="com.shsxt"/>
2.使用特定的注解
@Controller
public class ResourceController {
@Autowired
private ResourceService resourceService;
public void test() {
System.out.println("ResourceController...");
resourceService.test();
}
}
@Service
public class ResourceService {
@Resource
private ResourceDao resourceDao;
public void test() {
System.out.println("ResourceService...");
resourceDao.test();
}
}
@Repository
public class ResourceDao {
public void test() {
System.out.println("ResourceDao...");
}
}
@Component
public class PropertyUtils {
public void test(){
System.out.println("PropertyUtils...");
}
}
3.资源加载
public class Test03 {
public static void main(String[] args) {
BeanFactory factory=new ClassPathXmlApplicationContext("spring3.xml");
ResourceDao resourceDao= (ResourceDao) factory.getBean("resourceDao");
resourceDao.test();
ResourceService resourceService= (ResourceService) factory.getBean("resourceService");
resourceService.test();
ResourceController resourceController= (ResourceController) factory.getBean("resourceController");
resourceController.test();
ResourceUtil resourceUtil= (ResourceUtil) factory.getBean("resourceUtil");
resourceUtil.test();
}
}
四、Spring IOC扫描器实现用户登录
Controller层
public class UserController {
@Resource
private UserService userService;
/**
* 登录界面
* 接收参数,模拟数据
* 调用UserService层方法,返回resultInfo对象
* @param uname
* @param upwd
*/
public void Login(String uname,String upwd){
//调用service层方法
ResultInfo resultInfo=userService.loginService(uname,upwd);
System.out.println("显示信息:"+resultInfo);
}
}
Service层
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class UserService {
@Resource
private UserDao userDao;
/**
* 1.判断参数是否为空
* 为空,设置状态码和原因,返回resultInfo对象
* 2.根据name查询Dao层方法,返回User对象
* 3.判断用户是否为空
* 为空,设置状态码和原因,返回resultInfo对象
* 4.判断密码和数据库密码是否相等
* 不相等,设置状态码和原因,返回resultInfo对象
* 5.登录成功,返回resultInfo对象
*
* @param uname
* @param upwd
* @return
*/
public ResultInfo loginService(String uname, String upwd) {
ResultInfo resultInfo=new ResultInfo();
//判断参数是否为空
if(StringUtils.isBlank(uname)){
//状态码和原因
resultInfo.setCode(0);
resultInfo.setMsg("用户名不能为空!");
return resultInfo;
}
if(StringUtils.isBlank(upwd)){
//状态码和原因
resultInfo.setCode(0);
resultInfo.setMsg("密码不能为空!");
return resultInfo;
}
//调用Dao层方法,返回user对象
User user=userDao.loginDao(uname);
//判断用户是否为空
if(user==null){
//状态码和原因
resultInfo.setCode(0);
resultInfo.setMsg("用户不存在!");
return resultInfo;
}
//判断密码是否相等
if(!(user.getUpwd().equals(upwd))){
//状态码和原因
resultInfo.setCode(0);
resultInfo.setMsg("密码输入错误!");
}else{
//状态码
resultInfo.setCode(1);
resultInfo.setMsg("success");
resultInfo.setResult(user);
}
return resultInfo;
}
}
Dao层
@Repository
public class UserDao {
private Map<String,Object>map;
//模拟数据库数据
public UserDao(){
map=new HashMap<>();
User user=new User();
user.setUid(1);
user.setUname("admin");
user.setUpwd("123456");
map.put("admin",user);
}
public User loginDao(String uname) {
return (User) map.get(uname);
}
}
public class ResultInfo {
private Integer code;//状态码
private String msg;//提示信息
private Object result;//返回对象可以是list map 对象String JavaBean
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
@Override
public String toString() {
return "ResultInfo{" +
"code=" + code +
", msg='" + msg + '\'' +
", result=" + result +
'}';
}
}
public class User {
private Integer uid;
private String uname;
private String upwd;
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getUpwd() {
return upwd;
}
public void setUpwd(String upwd) {
this.upwd = upwd;
}
@Override
public String toString() {
return "User{" +
"uid=" + uid +
", uname='" + uname + '\'' +
", upwd='" + upwd + '\'' +
'}';
}
}
xml配置
<!--开启自动化扫描范围-->
<context:component-scan base-package="com.shsxt"/>
资源加载
public class TestDemo {
public static void main(String[] args) {
BeanFactory factory=new ClassPathXmlApplicationContext("spring.xml");
UserController userController= (UserController) factory.getBean("userController");
userController.Login("admin","123456");
}
}
五、Bean的作用域和生命周期
1.bean的作用域
实现
Bean的作用域
scope:
设置bean对象的作用域(singleton或prototype),默认singleton
singleton单例作用域
Spring IOC容器在实例化对象时,会将单例对象设置到单例缓存池中
/* lazy-init属性(懒加载)
如果为false,则在IOC容器启动时会实例化bean对象,默认false
如果为true,则IOC容器启动时不会实例化Bean对象,在使用bean对象时才会实例化
lazy-init设置为false有什么好处?
1、可以提前发现潜在的配置问题
2、Bean 对象存在于缓存中,使用时不用再去实例化bean,加快程序运行效率
什么对象适合作为单例对象?
无状态的对象 (不存在会改变对象状态的成员变量)
controller层、service层、dao层
*/
prototype原型作用域
Spring IOC容器在实例化对象时,不会将单例对象设置到单例缓存池中,每一次实例都是一个新的对象
Web作用域
request作用域
在每一次请求实例化一个bean对象
session作用域
在每一次有效会话实例化一个bean对象
globalSession作用域
类似于session
xml配置
<!-- singleton单例作用域:lazy-init懒加载-->
<bean id="resourceService" class="com.shsxt.service.ResourceService" lazy-init="false"></bean>
<!--prototype原型作用域-->
<bean id="resourceService" class="com.shsxt.service.ResourceService" scope="prototype"></bean>
2.bean的生命周期
Bean的生命周期
Bean的生命周期包括Bean的定义、初始化、使用和销毁4个阶段
定义
通过配置文档的方式来定义Bean的
初始化
默认在IOC容器加载时,就实例化对象
Spring bean 初始化有两种方式:
I.在配置文档中通过指定 init-method 属性来完成。
II.实现org.springframework.beans.factory.InitializingBean接口。
使用
I.使用BeanFactory
II.使用ApplicationContext
销毁
步骤一:实现销毁方式(Spring容器会维护bean对象的管理,可以指定bean对象的销毁所要执行的方法)
<bean id="userServiceImpl"class="com.shsxt.service.impl.UserServiceImpl" init-method="init" destroy-method="destroy">
</bean>
步骤二:过AbstractApplicationContext 对象,调用其close方法实现bean的销毁过程。
AbstractApplicationContext ctx=new ClassPathXmlApplicationContext("Spring-application.xml");
ctx.close();
public class RoleService implements InitializingBean {
/*初始化*/
public RoleService(){
System.out.println("RoleService被初始化。。。。。。");
}
public void test(){
System.out.println("RoleService........");
}
public void init(){
System.out.println("RoleService init........");
}
public void destroy() {
System.out.println("RoleService destroy...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("RoleService init afterPropertiesSet.....");
}
}
xml配置
<!--Bean生命周期-->
<bean id="roleService" class="com.shsxt.service.RoleService"></bean>
<!--init初始化-->
<bean id="roleService" class="com.shsxt.service.RoleService" init-method="init"></bean>
<!--实现org.springframework.beans.factory.InitializingBean接口。-->
<bean id="roleService" class="com.shsxt.service.RoleService" init-method="init"></bean>
<!--销毁-->
<bean id="roleService" class="com.shsxt.service.RoleService" destroy-method="destroy"></bean>
//销毁
// 通过AbstractApplicationContext 对象,调用其close方法实现bean的销毁过程
AbstractApplicationContext ct=new ClassPathXmlApplicationContext("spring4.xml");
System.out.println("销毁前:"+ct.getBean("roleService"));
ct.close();
System.out.println("销毁后:" + ct.getBean("roleService"));
六、定时任务
第一种:
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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd">
<!--开启自动化扫描范围-->
<context:component-scan base-package="com.shsxt"/>
<task:scheduled-tasks>
<!-- 每个两秒执行一次任务 -->
<task:scheduled ref="taskSchedule" method="job1" cron="0/2 * * * * ?"/>
<!-- 每隔五秒执行一次任务 -->
<task:scheduled ref="taskSchedule" method="job2" cron="0/5 * * * * ?"/>
<!-- 多个定时任务 在这里配置 -->
</task:scheduled-tasks>
</beans>
@Component
public class TaskSchedule {
public void job1(){
System.out.println("任务 1:"+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
}
public void job2(){
System.out.println("任务 2:"+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
}
}
加载资源
public class TestDemo {
public static void main(String[] args) {
BeanFactory factory = new ClassPathXmlApplicationContext("spring.xml");
TaskSchedule taskSchedule = (TaskSchedule) factory.getBean("taskSchedule");
}
}
第二种:
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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd">
<context:component-scan base-package="com.shsxt"/>
<!--配置定时任务驱动-->
<task:annotation-driven />
</beans>
@Component
public class TaskSchedule02 {
@Scheduled(cron="0/2 * * * * ?")
public void job1(){
System.out.println("任务 1:"+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
}
@Scheduled(cron = "0/5 * * * * ?")
public void job2(){
System.out.println("任务 2:"+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
}
}
加载资源
public class TestDemo {
public static void main(String[] args) {
BeanFactory factory = new ClassPathXmlApplicationContext("spring2.xml");
TaskSchedule taskSchedule02 = (TaskSchedule) factory.getBean("taskSchedule02");
}
}