Spring 基础知识 (一)

Spring 基础知识 (一)

1.1、为什么要使用Spring

问题1:代码耦合高

​ 先来看一段代码:

public class A {
    AInterface a;

    A()
    {
        a = new AInterfaceImp();
    }
}

​ 接口驱动编程有很多好处,它可以提供不同灵活的子类实现,增加代码稳定和健壮性等等,但是接口一定是需要实现的,也就是如下语句迟早要执行:IADAO ADAO = new ADAOImpl() 这样一来,耦合关系就产生了。
​ Class A与AInterfaceImp就是依赖关系,如果想使用AInterface的另外一个实现AInterfaceImpB就需要更改代码了。当然我们可以建立一个Factory来根据条件生成想要的AInterface的具体实现,即:

InterfaceImplFactory
{
   AInterface create(Object condition)
   {
      if(condition == condA)
      {
          return new AInterfaceImpA();
      }
      else if(condition == condB)
      {
          return new AInterfaceImpB();
      }
      else
      {
          return new AInterfaceImp();
      }
    }
}

​ 表面上是在一定程度上缓解了以上问题,但实质上这种代码耦合并没有改变。

问题2:控制事务的繁琐

​ 对于事务操作,必须在所有需要控制事务的地方,手动用代码完成几乎完全相同的事务控制逻辑,开发效率低下,产生大量代码冗余,并且难以方便的处理事务嵌套需求。

​ 如何降低业务逻辑部分之间耦合度,提高程序的可重用性,同时提高开发的效率,就成为了重点关注的内容。

AService{
    public void save(...){
      开启事务...
	  
      dao.save(...);
	  
      提交事务...
    }
    public void update(...){
      开启事务...
	  
      dao.update(...);
	  
      提交事务...
    }
}

1.2、Spring概述

  1. Spring是一个轻量级的DI/IoC和AOP容器的开源框架。
  2. Spring提倡以”最少侵入”的方式来管理应用中的代码,这意味着我们可以随时安装或卸载Spring。
  3. 非侵入式设计,从框架角度可以这样理解,无需继承框架提供的类,这种设计就可以看作是非侵入式设计,如果继承了这些框架类,就是侵入设计,如果以后想更换框架之前写过的代码几乎无法重用,如果非侵入式设计则之前写过的代码仍然可以继续使用。

IoC和DI

​ **IoC : **即“控制反转”,它是一种设计思想,不是一种技术。在开发中,这意味着将你设计好的对象交给一个容器控制,而不是传统的在你的对象内部直接控制。

​ 在传统的程序设计中,我们是直接在对象内部通过new关键字来创建对象,是程序主动去创建所依赖的对象;而现在,可以有一个专门的容器来创建这些对象,即由Ioc容器来控制对象的创建;由容器帮我们查找及注入所依赖的对象,你的对象只需要接受依赖的对象,并不需要再自己控制。

​ **DI : **即“依赖注入”,和字面意思一样,就是由容器动态的将某个依赖关系注入到代码之中,通过依赖注入机制,可以提升组件重用的频率,只需要通过简单的配置,就可指定目标需要的资源,不需要关心具体的资源来自何处,由谁实现。这里需要注意一点,注入是指注入某个对象所需要的外部资源,包括对象、资源、常量数据等,而不仅仅局限于对象。

​ DI是IoC的表现,IoC是DI的基础,其实就是同一个概念的不同描述。

​ 举个简单的例子来理解,这就像是在生活中的租房一样,常见的情况是,我们会到处去找要出租的房子,然后去看房子的价格、地段等等信息是不是符合我们的需求,需要自己处理其中的每个环节。

​ 现在我们有了中介所,就相当于IoC,我们现在要做的就是告诉中介,我需要一个什么样的房子,它需要满足什么条件,这在程序中就表现为接口,我们只需要等中介给我们选房子就可以了,整个选房子的过程不再由我自己控制,而是由中介这样一个类似容器的机构来控制。

​ 在理解了DI/IoC后,再来看看问题一,现在尝试着将问题一的代码改造一下:

BeanFactory类

//对象工厂
public enum BeanFactory {
    INSTANCE;
    private static Map<String, String> beanMap = new HashMap<>();
    // Map中的key就是对象的名字,value就是一个class对象.
    private Map<String, Object> cache = new HashMap<>();

    static {
        try {
            InputStream in = BeanFactory.class.getClassLoader()
                .getResourceAsStream("beans.xml");
            // 把beans.xml中的数据存放于Map中
            initBeanMap(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 约定优于配置:传递的name参数必须等于beanMap中的key(beans.xml中bean元素的id值)
    public <T> T getBean(String name, Class<T> requiredType) {
        if (!beanMap.containsKey(name)) {
            throw new RuntimeException("在beans.xml文件中找不到指定的" + name);
        }
        String className = beanMap.get(name);
        try {
            Object obj = cache.get(name);
            if (obj == null) {
                obj = Class.forName(className).newInstance();
                if (!requiredType.isInstance(obj)) {
                    throw new RuntimeException("bean类型不匹配");
                }
                cache.put(name, obj);
            }
            return (T) obj;
        } catch (Exception e) {
            throw new RuntimeException("创建对象bean失败", e);
        }
    }

    private static void initBeanMap(InputStream in) {
        try {
            SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
            parser.parse(in, new DefaultHandler() {
                private String tagName = null;

                public void startElement(String uri, String localName, String qName, Attributes attr) throws SAXException {
                    tagName = qName;
                    if ("bean".equals(tagName)) {
                        String id = attr.getValue("id");
                        String className = attr.getValue("class");
                        beanMap.put(id, className);
                    }
                }

                public void endElement(String uri, String localName, String qName) throws SAXException {
                    tagName = null;
                }

            });
        } catch (Exception e) {
            throw new RuntimeException("操作失败", e);
        }
    }
}

A类

public class A {

    public AInterface a;

    A()
    {
        a = BeanFactory.INSTANCE.getBean("AInterfaceImp", AInterface.class);
    }
}

beans.xml

<beans>
    <bean id="AInterfaceImp" class="com.demo.start.AInterfaceImp" />
</beans>

​ 通过IoC模式可以彻底解决问题一中的代码耦合,它把耦合从代码中移出去,放到统一的XML 文件中,通过一个容器在需要的时候把这个依赖关系形成,即把需要的接口实现注入到需要它的类中。

​ 采用依赖注入技术之后,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将对象在外部new出来并注入到主类里的引用中。而具体获取的方法、对象被获取时的状态由配置文件(如XML)来指定。

面向切面编程(AOP)

​ 关于AOP的相关内容将会在后面的文章中详细介绍,这里就不再赘述;

1.3、Spring使用

Spring需要的jar包

  <properties>
    <spring-version>5.2.1.RELEASE</spring-version>
  </properties>

  <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>${spring-version}</version>
          <scope>compile</scope>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>${spring-version}</version>
          <scope>compile</scope>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jcl</artifactId>
          <version>${spring-version}</version>
          <scope>compile</scope>
      </dependency>
      <!--Spring测试包-->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-test</artifactId>
          <version>${spring-version}</version>
          <scope>compile</scope>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>${spring-version}</version>
          <scope>compile</scope>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>${spring-version}</version>
          <scope>compile</scope>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-expression</artifactId>
          <version>${spring-version}</version>
          <scope>compile</scope>
      </dependency>
  </dependencies>

Spring示例程序

​ 创建一个applicationContext.xml文件,在applicationContext.xml中完成bean的配置。

<?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="helloword"  class="com.SpringDemo.HelloWorld" >
        <property name="name" value="zhangsan"/>
    </bean>
    
</beans>

​ 启动容器,从容器中得到bean,调用bean响应的方法。

public class HelloWorld {

    private String name;

    public void setName(String name) {
        this.name = name;
    }
    public void hello(){
        System.out.println("你好:"+name);
    }

    public static void main(String []args) throws Exception{
        HelloWorld helloWord = null;
        Resource resource = new ClassPathResource("applicationContext.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);
        helloWord = (HelloWorld) beanFactory.getBean("helloword");
        helloWord.hello();
    }
}

Spring中获取bean的三种方式

1.按照类型拿bean: 要求在Spring中只配置一个这种类型的实例
helloWord = (HelloWorld) beanFactory.getBean(HelloWorld.class);

2.按照bean的名字拿bean: 按照名字拿bean不太安全
helloWord = (HelloWorld) beanFactory.getBean("helloword");

3.按照名字和类型: 推荐使用这种方式
helloWord = (HelloWorld) beanFactory.getBean("helloword",HelloWorld.class);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值