栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

2021-10-20 SpringIOC控制反转

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

2021-10-20 SpringIOC控制反转

Spring IOC 主要内容

Spring框架 Spring框架概念

Spring是众多开源项目中的一员,基于分层的javaEE应用一站式轻量级开源框架,主要核心是IOC(控制反转/依赖注入)与AOP(面向切面)两大技术,实现项目在开发过程中的轻松解耦,提高项目的开发效率

在项目中引入Spring立即可以带来下面的好处降低组件之间的耦合度,实现软件各层之间的解耦.可以使用容器提供众多服务,如:事务管理服务,消息服务等等.当我们使用容器管理事务时,开发人员就不在需要手工控制事务.也不需处理复杂的事务传播.容器提供单例模式支持,开发人员不再需要自己编写实现代码.容器提供AOP技术,利用它很容易实现如权限拦截,运行期监控等功能.

Spring源码架构

Spring总共大约有20个模块,由1300多个不同的文件构成.而这些组件被分别整合在核心容器(Core Container),AOP(Aspect Oriented Programming)和设备支持(intermentation),数据访问及集成(Data Access/Integeration),Web,报文发送(Messaging),测试6个模块集合中.

​ 1.核心容器:Spring-beans和Spring-core模块是Spring框架的核心模块,包括控制反转(Inversion of Control,IOC)和依赖注入(Dependency Injection,DI),核心容器提供Spring框架的基本功能.核心容器的主要组件是BeanFactory,工厂模式的实现.BeanFactory使用控制反转(IOC)思想将应用程序的配置和依赖性规范与实际的应用程序代码分开.

​ Spring上下文Spring Context: Spring 上下文是一个配置文件,向Spring框架提供上下文信息.Spring上下文包括企业服务,例如JNDI,EJB,电子邮件,国际化,效验和调度功能.

​ Spring-expression模块是统一表达式语言(unified EL)的扩展模块,可以查询,管理运行中的对象,同时也方便的可以调用对象方法,操作数组,集合等.它的语法类似于传统的EL,但提供了额外的功能,最出色的要数函数调用和简单字符串的模板函数.

​ 2.Spring-AOP: Spring-aop是Spring的另一个核心模块,在Spring中,他是以JVM的动态代理技术为基础,然后设计出了 一系列的Aop横切实现,比如前置通知,返回通知,异常通知等.通过其配置管理特性,Spring AOP模块直接将面向切面的编程功能集中到了Spring框架中.所以.可以很容易地使Spring框架管理的任何对象支持AOP.

​ 3.Spring Data Access(数据访问): 由Spring-jdbc,Spring-tx,Spring-orm,Spring-jms和Spring-oxm5个模块组成Spring-jdbc模块是Spring提供的JDBC抽象框架的主要实现模块,用于简化Spring JDBC.

​ Spring-tx模块是SpringJDBC事务控制实现模块.使用Spring框架,它对事务做了很好的封装,通过它的Aop配置,可以灵活的配置在任何一层.

​ Spring-Orm模块是ORM框架支持模块,主要集成hibernate,Java Persistence API(JPA)和Java Data Objects (JDO)用于资源管理,数据访问对象(DAO)的实现和事务策略.

​ Spring-Jms模块(Java Messaging Service)能够发送和接收信息.

​ Spring-Oxm模块主要提供一个抽象层以支撑OXM(OXM是Object-to-XML-Mapping的缩写,它是一个O/M-mapper,将java对象映射成XML数据,或者将XML数据映射成java对象), 例如: JAXB , Castor,

XMLBeans,JiBX和XStream等.

​ 4.Web模块: 由Spring-web , Spring-webmvc , Spring-websocket和Spring-webmvc-portlet 4个模块组成.

​ web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文.Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作.

​ 5.报文发送:即Spring-massaging模块

​ Spring-massaging是Spring4新加入的一个模块,主要职责是为Spring框架继承一些基础的报文传送应用.

​ 6.单元测试: 即Spring-test模块. Spring - test 模块主要为测试提供支持.

Spring IOC容器Bean对象实例化模拟

思路:

​ 1.定义Bean工厂接口,提供获取bean方法

​ 2,定义Bean工厂接口实现类,解析配置文件,实例化Bean对象

​ 3.实现获取Bean方法

定义Bean属性对象
package com.xxxx.spring;

public class MyBean {
    private String id; // bean对象的id属性值
    private String clazz; // bean对象的类路径
    public MyBean() {
   }
    public MyBean(String id, String clazz) {
        this.id = id;
        this.clazz = clazz;
   }
    public String getId() {
        return id;
   }
    public void setId(String id) {
        this.id = id;
   }
    public String getClazz() {
        return clazz;
   }
    public void setClazz(String clazz) {
        this.clazz = clazz;
   }
}
添加dom4j坐标依赖

    dom4j
    dom4j
    1.6.1



    jaxen
    jaxen
    1.1.6

准备自定义配置文件

Spring.xml



    
    

测试自定义IOC容器

1.创建于配置文件中对应的Bean对象

​ UserService.java

package com.xxxx.service;
public class UserService {
    public void test(){
        System.out.println("UserService Test...");
   }
}

AccountService.java

package com.xxxx.service;
public class AccountService {
    public void test(){
        System.out.println("AccountService Test...");
   }
}

2.测试是否可以获取实例化的Bean对象

package com.xxxx;
import com.xxxx.spring.MyFactory;
import com.xxxx.spring.MyClassPathXmlApplicationContext;
import com.xxxx.service.AccountService;
import com.xxxx.service.UserService;
public class App {
    
    public static void main(String[] args) {
        MyFactory factory = new MyClassPathXmlApplicationContext("spring.xml");
        // 得到实例化对象
        UserService userService = (UserService) factory.getBean("userService");
        userService.test();
        UserService userService2 = (UserService) factory.getBean("userService");
        System.out.println(userService+"=====" + userService2);
        AccountService accountService =
       (AccountService)factory.getBean("accountService");
     accountService.test();
   }
}

Spring容器在启动的时候读取xml配置信息,并对配置的bean进行实例化(这里模拟的比较简单,仅用于帮助大家理解),同时通过上下文对象提供的getBean()方法拿到我们配置的bean对象,从而实现外部容器自动化维护并创建bean的效果.

Spring IOC配置文件加载 Spring 配置文件加载

Sring.xml



    
    

根据相对路径加载资源
ApplicationContext ac  = new ClassPathXmlApplicationContext("spring.xml");
根据绝对路径加载资源(了解)
ApplicationContext ac = newFileSystemXmlApplicationContext("C:/IdeaWorkspace/spring01/src/main/resources/spring.xml");
Spring多配置文件加载

Spring框架启动时可以加载多个配置文件到环境中.对于比较复杂的项目,可能对应的配置文件有多个,项目在启动部署时会将多个配置文件同时加载进来.

service.xml

        

dao.xml

        
可变参数,传入多个文件名
// 同时加载多个资源文件ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml","dao.xml");
通过总的配置文件import其他配置文件

spring.xml

                

加载时只需要总的配置文件即可

// 加载总的资源文件ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
Spring IOC容器Bean对象实例化 构造器实例化 注: 通过默认构造器创建空构造方法必须存在否则创建失败

​ 1.设置配置文件spring.xml

    

​ 2.获取实例化对象

ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");UserService userService = (UserService) ac.getBean("userService");  userService.test();
静态工厂实例化(了解)

注:

​ 要有该工厂类及工厂方法

​ 工厂方法为静态的

​ 1.定义静态工厂类

package com.xxxx.factory;import com.xxxx.service.UserService;public class StaticFactory {        public static UserService createUserService() {        return new UserService();   }}

​ 2.设置配置文件spring.xml

        

​ 3.获取实例化对象

ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");UserService userService = (UserService) ac.getBean("userService");  userService.test();

当我们指定Spring使用静态工厂方法来创建Bean实例时,Spring将先解析配置文件,并根据配置文件指定的信息,通过反射调用静态工厂类的静态工厂方法,并将该静态工厂方法的返回值作为Bean的实例,在这个过程中,Spring不再负责创建Bean实例,Bean实例是由用户提供的静态工厂方法提供的.

实例化工厂实例化(了解)

注:

​ 工厂方法为非静态方法

​ 需要配置工厂Bean,并在业务Bean中配置factory-bean, factory-method属性

1.定义工厂类

package com.xxxx.factory;import com.xxxx.service.UserService;public class InstanceFactory {        public UserService createUserService() {        return new UserService();   }}

2.设置配置文件spring.xml

            

3.获取实例化对象

ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");UserService userService = (UserService) ac.getBean("userService");  userService.test();
Spring三种实例化Bean的方式比较

方式一: 通过Bean的缺省构造函数创建,当各个Bean的业务逻辑相互比较独立的时候或者和外界关联较少的时候可以使用

方式二: 利用静态factory方法创建,可以统一管理各个Bean的创建,如各个Bean在创建之前需要相同的初始化处理,则可用这个factory方法进行统一处理等等.

方式三 : 利用实例化factory方法创建,即将factory方法也作为了业务Bean来控制,1可用于集成其他框架的Bean创建管理方法,2能够使Bean和factory的角色互换.

开发中项目一般使用一种方式实例化Bean,项目开发基本采用第一种方式,交给Spring托管,使用时直接拿来使用即可.另外两种了解

Spring IOC注入 手动实例化与外部引入

图一:

图二:

对比发现: 图二对于UserDao对象的创建没有像图一那样主动的去实例化,而是通过带参方法形式将UserDao传入过来,从而实现UserService对UserDao类的依赖.

而实际创建对象的幕后对象即是交给了外部来创建.

Spring IOC手动装配(注入)

Spring支持的注入方法共有四种: set注入, 构造器注入 , 静态工厂注入, 实例化注入

set方法注入

注:

​ 属性字段需要提供set方法

​ 四种方式,推荐使用set方法注入

业务对象JavaBean

​ 1.属性字段提供set方法

public class UserService {    // 业务对象UserDao set注入(提供set方法)    private UserDao userDao;    public void setUserDao(UserDao userDao) {        this.userDao = userDao;   }}

​ 2.配置文件的Bean标签设置property标签

                                
常用对象和基本类型

​ 1.属性字段提供set方法

public class UserService {// 常用对象String set注入(提供set方法)    private String host;    public void setHost(String host) {        this.host = host;   }    // 基本类型Integer   set注入(提供set方法)    private Integer port;    public void setPort(Integer port) {        this.port = port;   }}

​ 2.配置文件的Bean标签设置property标签

                                            public class UserService {    // List集合 set注入(提供set方法)    public List list;    public void setList(List list) {        this.list = list;   }       // Set集合 set注入(提供set方法)    private Set set;
集合类型和属性对象

​ 1.属性字段提供set方法

public class UserService {    // List集合 set注入(提供set方法)    public List list;    public void setList(List list) {        this.list = list;   }       // Set集合 set注入(提供set方法)    private Set set;      public void setSet(Set set) {        this.set = set;   }    // Map set注入(提供set方法)    private Map map;    public void setMap(Map map) {        this.map = map;   }        // Properties set注入(提供set方法)    private Properties properties;    public void setProperties(Properties properties) {        this.properties = properties;   }   }

2.配置文件的Bean标签设置property标签

                                上海            北京            杭州                                        上海SH            北京BJ            杭州HZ                                                          周杰伦                我是如此相信                                        林俊杰                可惜没如果                                        陈奕迅                十年                                                    东方明珠            天安门            西湖            
测试代码 UserService.java
public class UserService {    // 业务对象UserDao set注入(提供set方法)    private UserDao userDao;    public void setUserDao(UserDao userDao) {        this.userDao = userDao;   }    // 常用对象String set注入(提供set方法)    private String host;    public void setHost(String host) {        this.host = host;   }    // 基本类型Integer   set注入(提供set方法)    private Integer port;    public void setPort(Integer port) {        this.port = port;   }    // List集合 set注入(提供set方法)       public List list;    public void setList(List list) {        this.list = list;   }    // List集合输出    public void printList() {        list.forEach(s -> System.out.println(s));   }    // Set集合 set注入(提供set方法)    private Set set;    public void setSet(Set set) {        this.set = set;   }    // Set集合输出    public void printSet() {        set.forEach(s -> System.out.println(s));   }    // Map set注入(提供set方法)    private Map map;    public void setMap(Map 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.test();        studentDao.test();        System.out.println("Host:" + host  + ",port:" + port);        // List集合          printList();        // Set集合        printSet();        // Map        printMap();        // Properties        printProperties();   }}
Spring.xml
                                                                                                                 上海                北京                杭州                                                                上海SH                北京BJ                杭州HZ                                                                                    周杰伦                    我是如此相信                                                    林俊杰                    可惜没如果                                                    陈奕迅                    十年                                                                                东方明珠                天安门                西湖                        
构造器注入

注:

​ 提供带参构造器

单个Bean对象作为参数

Java代码

public class UserService {    private UserDao userDao; // JavaBean 对象        public UserService(UserDao userDao) {        this.userDao = userDao;   }    public  void  test(){        System.out.println("UserService Test...");        userDao.test();   }}

XML配置

                         
多个Bean对象作为参数

java代码

public class UserService {    private UserDao userDao;  // JavaBean 对象    private AccountDao accountDao  // JavaBean 对象            public UserService(UserDao userDao, AccountDao accountDao) {        this.userDao = userDao;        this.accountDao = accountDao;   }    public  void  test(){        System.out.println("UserService Test...");        userDao.test();        accountDao.test();   }}

XML配置

                                     
Bean对象和常用对象作为参数

Java代码

public class UserService {    private UserDao userDao;  // JavaBean 对象    private AccountDao accountDao;  // JavaBean 对象    private String uname;  // 字符串类型            public UserService(UserDao userDao, AccountDao accountDao, String uname) {        this.userDao = userDao;        this.accountDao = accountDao;        this.uname = uname;   }    public  void  test(){        System.out.println("UserService Test...");        userDao.test();        accountDao.test();        System.out.println("uname:" + uname);   }}

XML配置

                                         
循环依赖问题 循环依赖问题产生的原因:

Bean通过构造器注入,之间彼此相互依赖对方导致Bean无法实例化.

问题展示:

​ 1.Java代码

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...");   }}

​ 2.XML配置

        
如何解决: 将构造器注入改为set方法注入

​ 1.Java代码

public class AccountService {  private 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 void setAccountService(AccountService accountService) {  this.accountService = accountService;  }  public void test() {  System.out.println("RoleService Test...");  } } 

2.XML配置

        
静态工厂注入

​ 1.定义静态工厂类

public class StaticFactory {    // 定义静态方法    public static TypeDao createTypeDao() {        return new TypeDao();   }}

​ 2.Java代码

public class TypeService {    private TypeDao typeDao;     public void setTypeDao(TypeDao typeDao) {        this.typeDao = typeDao;   }    public void  test() {        System.out.println("TypeService Test...");   }}

​ 3.XML配置

​ 在配置文件中设置Bean标签,指定工厂对象并设置对应的方法

 
实例化工厂注入

​ 1.定义工厂类

public class InstanceFactory {     public TypeDao createTypeDao() {        return new TypeDao();   }}

​ 2.Java代码

public class TypeService {    private TypeDao typeDao;     public void setTypeDao(TypeDao typeDao) {        this.typeDao = typeDao;   }    public void  test() {        System.out.println("TypeService Test...");   }}

​ 3.XML配置

​ 声明工厂Bean标签,声明Bean对象,指明工厂对象和工厂方法

 
重点掌握set注入和构造器注入,工厂方式了解即可.实际开发中基本使用set方式注入Bean. 注入方式的选择 开发项目中set方式注入首选

使用构造注入可以在构建对象的同时一并完成依赖关系的建立,对象一建立则所有的一切也就准备好了,但如果要建立的对象关系很多,使用构造器注入会在构建函数上留下一长串的参数.且不易记忆,这时使用set注入会是一个不错的选择. 使用set注入可以有明确的名称,可以了解注入的对象会是什么,像setXXX()这样的名称就会比记忆Constructor上某个参数的位置代表某个对象更好.

P名称空间的使用

Spring2.5以后,为了简化setter方法属性注入,引用p名称空间的概念,可以将子元素,简化为元素属性配置.

​ 1.属性字段提供set方法

public class UserService {    // 业务对象UserDao set注入(提供set方法)    private UserDao userDao;    public void setUserDao(UserDao userDao) {        this.userDao = userDao;   }        // 常用对象String set注入(提供set方法)    private String host;    public void setHost(String host) {        this.host = host;   }}

2.在配置文件Spring.xml引入p名称空间

xmlns:p="http://www.springframework.org/schema/p"
             
Spring IOC自动装配(注入) 注解方式注入Bean

对于Bean的注入,除了使用xml配置以外,可以使用注解配置.注解的配置,可以简化配置文件,提高开发的速度,使程序看上去更简洁.对于注解的解释,Spring对于注解有专门的解释器,对定义的注解进行解析,实现对应Bean对象的注入.通过反射技术实现.

准备环境

​ 1.修改配置文件


​ 2.开启自动化注入


​ 3.给注入的Bean对象添加注解

@Resource注解

@Resource注解实现自动注入(反射)

​ 默认根据属性字段名称查找对应的Bean对象(属性字段的名称与Bean标签的id属性值相等)

​ 如果属性字段名称未找到,则会通过类型(class类型)查找

​ 属性可以提供set方法,也可以不提供set方法

​ 注解可以声明在属性级别或set方法级别

​ 可以设置name属性,name属性值必须与Bean标签的id属性值一致;如果设置了name属性值,就只会按照name属性值查找Bean对象

​ 当注入接口时,如果接口只有一个实现则正常实例化; 如果接口存在多个实现,则需要使用name属性指定需要被实例化的Bean对象

代码示例

​ 1.默认根据属性字段名称查找对应的Bean对象(属性字段的名称与Bean标签的id属性值相等)

public class UserService {    @Resource    private UserDao userDao; // 属性字段的名称与bean标签的id属性值相等    public void setUserDao(UserDao userDao) {        this.userDao = userDao;   }    public void test() {        // 调用UserDao的方法        userDao.test();   }}

​ 2.如果属性字段名称未找到,则会通过类型(class类型)查找

public class UserService {    @Resource    private UserDao ud; // 当在配置文件中属性字段名(ud)未找到,则会查找对应的class(UserDao类型)    public void setUd(UserDao ud) {        this.ud = ud;         }    public void test() {        // 调用UserDao的方法        ud.test();   }}

​ 3.属性可以提供set方法,也可以不提供set方法

public class UserService {    @Resource    private UserDao userDao; // 不提供set方法    public void test() {        // 调用UserDao的方法        userDao.test();   }}

​ 4.注解可以声明在属性级别或set方法级别

public class UserService {    private UserDao userDao;    @Resource // 注解也可设置在set方法上    public void setUserDao(UserDao userDao) {        this.userDao = userDao;   }    public void test() {        // 调用UserDao的方法        userDao.test();   }}

​ 5.可以设置name属性,name属性值必须与Bean标签的id属性一致;如果设置了name属性值,就只会按照name属性值查找Bean对象

public class UserService {    @Resource(name = "userDao") // name属性值与配置文件中bean标签的id属性值一致    private UserDao ud;    public void test() {        // 调用UserDao的方法        ud.test();   }}

​ 6.当注入接口时,如果接口只有一个实现则正常实例化;如果接口存在多个实现,则需要使用name属性指定需要被实例化的Bean对象

​ 定义接口类IUserDao.java

package com.xxxx.dao;public interface IUserDao {    public void test();}

​ 定义接口的实现类 UserDao01

package com.xxxx.dao;public class UserDao01 implements IUserDao {    @Override    public void test(){        System.out.println("UserDao01...");   }}

​ 定义接口实现类UserDao02

package com.xxxx.dao;public class UserDao02 implements IUserDao {    @Override    public void test(){        System.out.println("UserDao02...");   }}

XML配置文件

    

使用注解 UserService.java

public class UserService {    @Resource(name = "userDao01") // name属性值与其中一个实现类的bean标签的id属性值一致    private IUserDao iUserDao; // 注入接口(接口存在多个实现)    public void test() {        iUserDao.test();   }}
@Autowired注解

@Autowrite注解实现自动化注入:

​ 默认通过类型(class类型)查找Bean对象与属性字段的名称无关

​ 属性可以提供set方法,也可以不提供set方法

​ 注解可以声明在属性级别或set方法级别

​ 可以添加@Qualifier结合使用,通过value属性值查找Bean对象(value属性值必须要设置,且值要与Bean标签的id属性值对应)

1.默认通过类型(Class类型)查找Bean对象与属性字段的名称无关

public class UserService {    @Autowired    private UserDao userDao; // 默认通过类型(Class类型)查找bean对象 与属性字段的名称无关    public void setUserDao(UserDao userDao) {        this.userDao = userDao;   }    public void test() {        // 调用UserDao的方法        userDao.test();   }}

2.属性可以提供set方法,也可以不提供set方法

public class UserService {    @Autowired    private UserDao userDao; // 不提供set方法    public void test() {        // 调用UserDao的方法        userDao.test();   }}

3.注解可以声明在属性级别或set方法级别

public class UserService {    private UserDao userDao;     @Autowired// 注解可以声明在set方法级别    public void setUserDao(UserDao userDao) {        this.userDao = userDao;   }    public void test() {        // 调用UserDao的方法        userDao.test();   }}

4.可以添加@Qualifier结合使用,通过value属性值查找Bean对象(value属性值必须要设置,且值要与Bean标签的id属性值对应)

public class UserService {    @Autowired    @Qualifier(value="userDao") // value属性值必须要设置,且值要与bean标签的id属性值对应    private UserDao userDao;    public void test() {        userDao.test();   }}

推荐使用@Resource注解是属于J2EE的,减少与Spring的耦合.

Spring IOC扫描器

实际开发中,Bean的数量非常多,采用手动配置Bean的方式已无法满足生产需要,Spring这时候同样提供了扫描的方式,对扫描到的Bean对象统一进行管理,简化开发配置,提高开发效率.

Spring IOC扫描器的配置
Spring IOC 扫描器	作用: Bean对象同意进行管理,简化开发配置,提高开发效率	1.设置自动化扫描范围			如果Bean对象未在指定包范围,即使声明了注解,也无法实例化	2.使用指定的注解(声明在类级别) Bean对象的id属性默认是类的首字母小写		Dao层:			@repository		service层:			@Service		Controller层:			@Controller		任意类:			@component	注:开发过程中建议按照指定规则声明注解

​ 1.设置自动化扫描范围

        

​ 2.使用特定的注解

​ @Repository(Dao层)

@Repositorypublic class ResourceDao {    public void  test() {        System.out.println("ResourceDao...");   }}

​ @Service(Service层)

@Servicepublic class ResourceService {    @Resource    private ResourceDao resourceDao; // service层注入dao层的bean对象    public  void  test() {        System.out.println("ResourceService...");        resourceDao.test();   }}

​ @Controller(Controller层)

@Controllerpublic class ResourceController {    @Autowired    private ResourceService resourceService; // Controller层注入service层的bean对象    public  void  test() {        System.out.println("ResourceController...");        resourceService.test();   }}

​ @Component(任意层)

@Componentpublic class PropertyUtils {    public void test(){        System.out.println("PropertyUtils...");   }}
Spring模拟用户登录流程 Dao层(查询用户记录)

​ 1.定义JavaBean User.java

package com.xxxx.po;public class User {    private String userName; // 用户名称    private String userPwd; // 用户密码    public String getUserName() {        return userName;   }    public void setUserName(String userName) {        this.userName = userName;   }    public String getUserPwd() {        return userPwd;   }    public void setUserPwd(String userPwd) {        this.userPwd = userPwd;   }} 

​ 2.编写Dao层UserDao.java

package com.xxxx.dao;import com.xxxx.po.User;import org.springframework.stereotype.Repository;@Repositorypublic class UserDao {        private final String USERNAME = "admin";    private final String USERPWD = "admin";            public User queryUserByUserName(String userName){        User user = null;        // 判断用户名称是否正确        if(!USERNAME.equals(userName)){            // 如果不正确,返回null            return null;       }        // 如果正确,将用户名称和密码设置到user对象中        user = new User();        user.setUserName(USERNAME);        user.setUserPwd(USERPWD);        return user;   }}
Service层(业务逻辑处理)

​ 1.定义业务处理返回消息模型 MessageModel.java

package com.xxxx.po.vo;public class MessageModel {    private Integer resultCode = 1; // 结果状态码 1=成功,0=失败    private String resultMsg = "操作成功!"; // 结果提示信息    public Integer getResultCode() {        return resultCode;   }    public void setResultCode(Integer resultCode) {        this.resultCode = resultCode;   }    public String getResultMsg() {        return resultMsg;   }    public void setResultMsg(String resultMsg) {        this.resultMsg = resultMsg;   }}

​ 2.编写Service层UserService.java

package com.xxxx.service;import com.xxxx.dao.UserDao1;import com.xxxx.po.User;import com.xxxx.po.vo.MessageModel;import org.springframework.stereotype.Service;import javax.annotation.Resource;@Servicepublic class UserService {    @Resource    private UserDao userDao;        public MessageModel userLoginCheck(String userName, String userPwd){        // 定义业务处理返回消息模型        MessageModel messageModel = new MessageModel();        // 判断用户名称是否非空        if(null == userName || "".equals(userName.trim())){            messageModel.setResultCode(0);            messageModel.setResultMsg("用户名不能为空!");            return messageModel;       }        // 判断用户密码是否为空        if(null == userPwd || "".equals(userPwd.trim())){            messageModel.setResultCode(0);            messageModel.setResultMsg("密码不能为空!");            return messageModel;       }        // 通过用户名称查询用户对象        User user = userDao.queryUserByUserName(userName);        // 判断用户对象是否为空        if(null == user){            messageModel.setResultCode(0);            messageModel.setResultMsg("该用户不存在!");            return messageModel;       }        // 如果用户对象不为空,判断密码是否正确        if(!user.getUserPwd().equals(userPwd)){            messageModel.setResultCode(0);            messageModel.setResultMsg("用户密码不正确!");            return messageModel;       }        // 登录成功        messageModel.setResultMsg("登录成功!");                return messageModel;   }}
Controller层(接收请求)

1.编写Controller层UserController.java

package com.xxxx.controller;import com.xxxx.po.vo.MessageModel;import com.xxxx.service.UserService1;import org.springframework.stereotype.Controller;import javax.annotation.Resource;@Controllerpublic class UserController {    @Resource    private UserService userService;        public MessageModel login(String userName, String userPwd){        // 调用Dao层判断用户登录操作,返回结果        MessageModel messageModel = userService.userLoginCheck(userName, userPwd);        return messageModel;   }}
通过JUnit进行测试
package com.xxxx;import com.xxxx.controller.UserController;import com.xxxx.po.vo.MessageModel;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestLogin {    @Test    public void test() {        // 得到Spring容器上下文环境        ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");        // 得到UserController实例化对象       UserController userController = (UserController) ac.getBean("userController");        // 传入参数调用UserController的方法,返回封装类        MessageModel messageModel= userController.login("admin", "admin");        System.out.println("状态码:" + messageModel.getResultCode() + ",提示信息:" +messageModel.getResultMsg());   }}
Bean的作用域与生命周期 Bean的作用域

默认情况下,我们从Spring容器中拿到的对象是单例的,对于Bean的作用域类型如下:

singleton作用域

注意:lazy-init是懒加载,如果等于true时作用是指Spring容器启动的时候不会去实例化这个Bean,而是在程序调用时才去实例化.默认是false即Spring容器启动时实例化.

默认情况下,被管理的Bean只会在IOC容器中存在一个实例,对于所有获取该Bean的操作Spring容器将只返回同一个Bean.

容器在启动的情况下就实例化所有singleton的Bean对象,并缓存与容器中

**lazy-init属性(懒加载)**如果为false,则在IOC容器启动时会实例化Bean对象,默认false如果为true,则IOC容器启动时不会实例化Bean对象,在使用Bean对象时才会实例化

lazy-init设置为false有什么好处? 1)可以提前发现潜在的配置问题 2)Bean对象存在于缓存中,使用时不用再去实例化Bean,加快程序运行效率

什么对象适合作为单例对象? 一般来说对于无状态或状态不可以改变的对象适合使用单例模式.(不存在会改变对象状态的成员变量) 比如: contoller层, service层, dao层

什么是无状态或状态不可改变的对象?

实际上对象状态的变化往往均是由于属性值的变化引起的,比如user类姓名属性会有变化,属性姓名的变化一般会引起user对象状态的变化.对于我们的程序来说,无状态对象没有实例变量的存在,保证了线程的安全性,service层业务对象即是无状态对象.线程安全.

prototype作用域

通过scope="prototype"设置Bean的类型,每次向Spring容器请求获取Bean都返回一个全新的Bean,相对于"singleton"来说就是不缓存Bean,每次都是一个根据Bean定义创建的全新Bean/

Web应用中的作用域 1.request作用域

​ 表示每个请求需要容器创建一个全新Bean.比如提交表单的数据必须是每次请求新建一个Bean来 保持这些表单数据,请求结束释放这些数据.

2.session作用域

​ 表示每个会话需要容器创建一个全新Bean.比如对于每个用户一般会有一个会话,该用户的用户信 息需要存储到会话中,此时可以将该Bean作用域配置为session级别

3.globalSession作用域

​ 类似于session作用域,其用于portlet(portlet是基于java的Web组件,由Portlet容器管理处理请求,生产动态内容)环境的web应用.如果在非portlet环境将视为session作用域.

配置方式和基本的作用域相同,只是必须要有web环境支持,并配置相应的容器监听器或拦截器从而能应用这些作用 域,目前先熟悉概念,后续集成web时讲解具体使用,大家只需要知道有这些作用域就可以了。

Bean的生命周期

对比已经学过的servlet生命周期(容器启动装载并实例化servlet类,初始化servlet,调用service方法,销毁servlet)

同样对于Spring容器管理的Bean也存在生命周期的概念

在Spring中,Bean生命周期包括Bean的定义,初始化,使用和销毁4个阶段

Bean的定义

在Spring中,通常是通过配置文档的方式来定义Bean的.

在一个配置文档中,可以定义多个Bean.

Bean的初始化

默认在IOC容器加载时,实例化对象.

Spring Bean初始化有两种方式:

**方式一:**在配置文档中通过指定init-method属性来完成.

public class RoleService {    // 定义初始化时需要被调用的方法    public void init() {        System.out.println("RoleService init...");   }}

**方式二:**实现org.springframework.beans.factory.InitializingBean接口.

public class RoleService implements InitializingBean {    @Override    public void afterPropertiesSet() throws Exception {        System.out.println("RoleService init...");   }}

Bean对象实例化过程是在Spring容器初始化时被实例化的,但也不是不可改变的,可以通过lazy-init="true"属性延迟Bean对象的初始化操作,此时再调用getBean方法时才会进行Bean的初始化操作.

Bean的使用

**方式一:**使用BeanFactory

//得到Spring的上下文环境BeanFactory  factory  =  new ClassPathXmlApplicationContext("spring.xml");RoleService  roleService  =  (RoleService)factory.getBean("roleService");

**方式二:**使用ApplicationContext

//得到Spring的上下文环境ApplicationContext  ac  =   new ClassPathXmlApplicationContext("spring.xml");RoleService  roleService  =  (RoleService)ac.getBean("roleService");
Bean的销毁

实现销毁方式(Spring容器会维护Bean对象的管理,可以指定Bean对象的销毁所要执行的方法).

**步骤一:**实现销毁方式(Spring容器维护Bean对象的管理,可以指定Bean对象的销毁所要执行的方法)

 

**步骤二:**通过AbstractApplicationContext对象,调用其close方法实现Bean的销毁过程

AbstractApplicationContext  ctx = new ClassPathXmlApplicationContext("Spring.xml");ctx.close();
IOC/DI-控制反转和依赖注入	将对象实例化的创建过程转交给外部容器(IOC容器  充当工厂角色)去负责;属性赋值的操作;
Bean的生命周期

对此已经学过的Servlet生命周期(容器启动装载并实例化servlet类,初始化servlet,调用service方法,销毁servlet).

同样对于Spring容器管理的Bean也存在生命周期的概念

在Spring中,Bean的生命周期包括Bean的定义,初始化,使用和销毁4个阶段 Bean的定义

在Spring中,通常是通过配置文档的方式来定义Bean的.

在一个配置文档中,可以定义多个Bean.

Bean的初始化

默认在IOC容器加载时,实例化对象.

Spring Bean 初始化有两种方式:

**方式一:**在配置文档中通过指定init-method属性来完成.

public class RoleService{    //定义初始化时需要被调用的方法    public vold init(){        System.out.println("RoleService  init...");    }}

**方式二:**实现 org.springframework.beans.factory.InitializingBean 接口。

public class RoleService implements InitializingBean {    @Override    public void afterPropertiesSet() throws Exception {        System.out.println("RoleService init...");   }}

Bean对象实例化过程是在Spring容器初始化时被实例化的,但也不是不可改变的,可以通过lazy-init="true"属性延迟Bean对象的初始化操作,此时再调用getBean方法时才会进行Bean的初始化操作

Bean的使用

**方式一:**使用BeanFactory

// 得到Spring的上下文环境BeanFactory factory = new ClassPathXmlApplicationContext("spring.xml");RoleService roleService = (RoleService) factory.getBean("roleService");

**方式二:**使用ApplicationContext

// 得到Spring的上下文环境ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");RoleService roleService = (RoleService) ac.getBean("roleService");
Bean的销毁

实现销毁方式(Spring容器会维护Bean对象的管理,可以指定Bean对象的销毁所要执行的方法).

**步骤一:**实现销毁方式(Spring容器会维护Bean对象的管理,可以指定Bean对象的销毁所要执行的方法)


**步骤二:**通过AbstractApplicationContext对象,调用其close方法实现Bean的销毁过程

AbstractApplicationContext ctx=new ClassPathXmlApplicationContext("spring.xml");ctx.close();
IOC/DI-控制反转和依赖注入	将对象实例化的创建过程交给外部容器(IOC容器  充当工厂角色)去负责;属性赋值的操作'
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/340362.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号