美文网首页
一起来学习Spring:Spring入门与IOC篇

一起来学习Spring:Spring入门与IOC篇

作者: __y | 来源:发表于2018-06-02 21:30 被阅读52次

1.Spring的基本介绍

spring:从翻译来说是春天的意思,意思是给软件开发带来了春天(想象下春天的美好~),spring的作者的初衷是让现有的技术更加实用,不是创造轮子,而是使轮子更好的运转。他就是一个大杂烩,整合了现有的技术

spring的优点

1.轻量级框架,不具有侵入性,方便框架的整合;
2.IOC容器:控制反转;
3.AOP:面向切面编程;
4.对事务的支持;

spring的主要内容

image.png
  • Test:spring支持Junit单元测试
  • 核心容器(IOC):Bean(Bean工厂,创建对象),Core(核心,一切的基础),Context(上下文),SpEL(spring的表达式语言)
  • AOP:面向切面编程
  • 对数据访问的支持:jdbc,ORM(Mybatis等),Transaction(事务的管理),JMS(java邮件服务)
  • Web:Spring MVC

2. IOC(Inversion of Control 控制反转)

下面用代码的形式看一下IOC的设计思想
创建对象由spring来创建,装配
DAO层:


public interface UserDao {
    public void getUser();
}

DAO层的实现层:
我们现在有一个实现DAO层的类,是Mysql的

public class UserDaoMysqlImpl implements UserDao {
    @Override
    public void getUser() {
        System.out.println("获取----Mysql");
    }
}

Oracle的

public class UserDaoMysqlImpl implements UserDao {
    @Override
    public void getUser() {
        System.out.println("获取----Mysql");
    }
}

service的接口层,定义接口,通过DAO层取=数据

public interface UserService {
    public void getUser();
}

service的实现层:

import dao.UserDao;
import daoimpl.UserDaoMysqlImpl;//可以去掉了
import service.UserService;

public class UserServiceImpl implements UserService {
    //自己创建的对象,现在获取的是Mysql,后面如果我想要换成Oracle的时候就要改代码
    //后面涉及到的代码越来越多的话,耦合性越来越大
    //private UserDao userDao = new UserDaoMysqlImpl();

    //进一步修改代码
    private UserDao userDao = null;
    //对外提供一个设置的方法
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void getUser() {
        userDao.getUser();
    }
}

Test(相当于客户端)

public class Test {
    public static void main(String[] args) {
        //在这里创建对象

        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(new UserDaoMysqlImpl());
        userService.getUser();
    }
}

分析:
1.我们可以看一下private UserDao userDao = new UserDaoMysqlImpl();这条语句是我们手动new出来的,这时候我们可以通过userDao这个对象去调用对应的方法。这没问题,但是如果以后我要改成Oracle,后面涉及到的代码越来越多的话,耦合性越来越大。 这样我们要改的代码就会很多,这是不利于我们后面的代码维护的。
2.我们看进一步修改后的代码,我们对外提供一个接口setUserDao方法来设置userDao,这样看起来是不是不管我们以后要改成什么Oracle还是Mysql,只要是实现Dao方法的传进来一个对象可以了。
3.我们再观察Test类,Test类就相当于客户端,UserServiceImpl就相当于应用程序了,应用程序不用再自己new对象,完全是将new对象的这个步骤交给了Test类(客户端),在由必要的时候才在客户端new一个对象。现在看起来还是我们手动的,但是如果我们将这些交给配置文件,我们就省了这一步功夫了。
通过上面的例子,我们可以得出IOC的好处:

  • 对象原来是程序本身创建的,变成了程序接收对象;
  • 我们在开发的时候可以更加地注重业务的开发
  • 实现了service和dao层的解耦工作,没有直接的依赖关系(举个简单的例子,我们可以把包含UserDaoMysqlImpl这个类的包名去掉了)

3.SpringIOC实现

我们在http://repo.springsource.org/libs-release-local/org/springframework/spring中下载对应的jar包


这里插入一个知识点:
IOC和DI(依赖注入,Dependency Injection)的区别
1.IOC:是把对象的创建交给Spring管理,由SpringIOC容器来创建对象,管理依赖关系
2.DI:依赖注入,在创建对象的过程中,向类里面的属性设置值
3.IOC和DI关系:依赖注入不能单独存在,必须在控制反转的基础上完成,就是注入类里面的属性值,不能直接注入,必须创建类的对象再完成注入


1.导入相关的jar包

image.png

2.创建配置文件和相关的实体类

public class Hello {
    private String name;

    public void setName(String name) {
        this.name = name;
    }
}

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">
    <bean id = "hello" class="com.spring.test.Hello">
        <property name="name" value="Spring的使用者"></property>
    </bean>
</beans>

创建一个测试类

package test;

import com.spring.test.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestBean {
    public static void main(String[] args) {
      //加载spring的配置文件,将配置文件中的对象进行创建
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("ApplicationContext.xml");
      //根据配置文件的id获得Hello对象
        Hello hello = (Hello)applicationContext.getBean("hello");
        hello.show();
    }
}

结果:


image.png

4.Spring的bean管理

上面我们已经看到了基本的实现,下面我们来详细介绍一下bean的管理,有两种方式

  • 使用配置文件方式实现(如上文)
  • 使用注解的方式

Spring实例化bean的三种方式:

1.通过无参构造方法
2.通过有参构造方法
3.通过工厂模式:

  • 工厂静态
  • 工厂非静态
    上文已经展示了无参构造方法了,下面重点介绍剩下的两种

通过有参构造方法

首先我们看看实体类(必须有带参数的构造方法)

public class User {
    private  int id;
    private  String name;

    public User(int id,String  name) {
        this.id = id;
        this.name = name;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

bean配置

<bean id = "user" class="com.spring.test.User">
        <constructor-arg index="0" name = "id"  value="1"></constructor-arg>
        <constructor-arg index="1" name = "name" value="大帅比"></constructor-arg>
    </bean>

测试类:

public class TestBean {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        User user = (User)applicationContext.getBean("user");
        System.out.println(user.getId() + " " + user.getName());
    }
}

image.png
PS:
在constructor如果构造函数的值是一个对象,而不是一个普通的类型的值,我们就需要用到ref属性,而不是value属性
比如说
我在User对象上维护了Address对象的值,想要在构造函数中初始化
   <bean id = "address" class="Address"></bean>
bean id = "user" class="com.spring.test.User">
        <constructor-arg index="0" name = "id"  value="1"></constructor-arg>
        <constructor-arg index="1" name = "address"  ref = "address"></constructor-arg>
    </bean>

工厂静态方法

写一个Factory

public class Factory {
    public static  User getBean() {
        return new User();
    }
}

 <bean id = "user" class="com.spring.test.Factory" factory-method="getBean"></bean>
image.png

工厂非静态方法

public class Factory {
    public   User getBean() {
        return new User();
    }
}
   <bean id="factory" class="com.spring.test.Factory"></bean>
    <bean id = "user"  factory-bean="factory" factory-method="getBean"></bean>

装载集合(setter注入,要有set方法)

如果对象上的属性或者构造函数具有集合的时候,我们又要为其赋值,可以通过以下赋值:
在构造函数中

 <bean id = "user"   class="com.spring.test.User">
        <constructor-arg>
            <list>
                //基本类型
                <value></value>
            </list>
        </constructor-arg>
    </bean>

在属性上

<bean id = "user"   class="com.spring.test.User">
        <property name="name">
            <list>
                //引用类型
                <ref></ref>
            </list>
        </property>
    </bean>

5.Spring配置文件中bean标签中的属性讲解

  • id:唯一的标志,只能唯一
  • class属性:要创建的对象的全路径
  • scope:bean的作用范围
    1.singleton:创建的对象是单例的,也是scope属性的默认值
    2.prototype:创建的对象是多例的
    3.globalSession:用在单点登录上即(SSO,single sign on)

6.注解的方式使用bean

上面我们可以的看到,如果我们的Bean不断增加的话,bean配置会越来越多,自己也会越来越乱,这个时候我们推荐使用注解的方式来优化我们的编码过程

1.引入context命名空间

xmlns:context="http://www.springframework.org/schema/context"

2.开启注解扫描器

 <context-:component-scan base-package="com.spring"></context-:component-scan>

3使用Repository注解

//把对象添加到容器中,首字母会小写
@Repository("userDao")
public class UserDaoMysqlImpl implements UserDao {
    @Override
    public void getUser() {
        System.out.println("获取----Mysql");
    }
}

4.使用Service注解

//把UserService对象添加到IOC容器中,首字母会小写
@Service("userService")
public class UserServiceImpl implements UserService {

    //如果@Resource不指定值,那么就根据类型来找--->UserDao....当然了,IOC容器不能有两个UserDao类型的对象
    //@Resource

    //如果指定了值,那么Spring就在IOC容器找有没有id为userDao的对象。
    @Resource(name = "userDao")
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void getUser() {
        userDao.getUser();
    }
}

5.使用Controller注解

@Controller
public class Test {
    @Resource(name = "userService")
    private UserService userService;
    public static void main(String[] args) {
        //在这里创建对象
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        UserService userService  = (UserService) applicationContext.getBean("userService");
        userService.getUser();
    }
}

常用注解:

  • @ComponentScan扫描器

  • @Configuration表明该类是配置类

  • @Component 指定把一个对象加入IOC容器--->@Name也可以实现相同的效果【一般少用】

  • @Repository 作用同@Component; 在持久层使用

  • @Service 作用同@Component; 在业务逻辑层使用

  • @Controller 作用同@Component; 在控制层使用

  • @Resource 依赖关系

如果@Resource不指定值,那么就根据类型来找,相同的类型在IOC容器中不能有两个

如果@Resource指定了值,那么就根据名字来找

相关文章

网友评论

      本文标题:一起来学习Spring:Spring入门与IOC篇

      本文链接:https://www.haomeiwen.com/subject/fatajftx.html