spring概述(一)--简介及helloworld案例

一.遇到的问题

1:代码高耦合

public class EmployeeServiceImpl {
      //依赖DAO
      private IEmployeeDAO employeeDAO = new EmployeeDAOImpl();
}

问题:若把IEmployeeDAO的实现改成:EmployeeMapper.
----->简单工厂设计模式
----->把创建对象的职责交给工厂来管理.
到底工厂创建哪一个类的对象呢?我们是配置在配置文件中的(properties/xml).

2:业务代码中处理事务的繁琐问题
对于事务操作,代码冗余,必须在所有需要控制事务的地方,手动用代码完成几乎完全相同的事务控制逻辑,开发效率低下,并且难以方便的处理事务嵌套需求。
如何降低业务逻辑部分之间耦合度,提高程序的可重用性,同时提高开发的效率!—> AOP
主要分散在方法前后,在真正的业务操作前后的代码,我们可以使用面向切面编程来解决.

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

3:使用表现层和持久层框架的繁琐步骤

二.Spring介绍

什么是spring:
1、Spring是一个轻量级的DI/IoC和AOP容器的开源框架,来源于Rod Johnson 在其著作《Expert one on one J2EE design and development》中阐述的部分理念和原型衍生而来。
2、Spring提倡以”最少侵入”的方式来管理应用中的代码,这意味着我们可以随时安装或卸载Spring。

使用范围:任何Java应用
Spring根本使命:简化Java开发
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,致力于构建轻量级的JavaEE应用

Spring中常见术语:

1、应用程序:是能完成我们所需要功能的成品,比如购物网站、OA系统。
2、框架:是能完成一定功能的半成品,比如我们可以使用框架进行购物网站开发;框架做一部分功能,我们自己做一部分功能,这样应用程序就创建出来了。而且框架规定了你在开发应用程序时的整体架构,提供了一些基础功能,还规定了类和对象的如何创建、如何协作等,从而简化我们开发,让我们专注于业务逻辑开发。
3、非侵入式设计:从框架角度可以这样理解,无需继承框架提供的类,这种设计就可以看作是非侵入式设计,如果继承了这些框架类,就是侵入设计,如果以后想更换框架之前写过的代码几乎无法重用,如果非侵入式设计则之前写过的代码仍然可以继续使用。
4、轻量级及重量级:轻量级是相对于重量级而言的,轻量级一般就是非入侵性的、所依赖的东西非常少、资源占用非常少、部署简单等等,其实就是比较容易使用,而重量级正好相反。
5、POJO:POJO(Plain Old Java Objects)简单的Java对象,它可以包含业务逻辑或持久化逻辑,但不担当任何特殊角色且不继承或不实现任何其它Java框架的类或接口。
6、容器(Container):在日常生活中容器就是一种盛放东西的器具,从程序设计角度看就是装对象的的对象,因为存在放入、拿出等操作,所以容器还要管理对象的生命周期。

Spring的优势:

1.低侵入/低耦合(降低组件之间的耦合度,实现软件各层之间的解耦。)
2.声明式事务管理
3.方便集成其他框架
4.降低JavaEE开发难度
5.Spring框架中包括JavaEE三层的每一层的解决方案 (一站式)

Spring能帮我们做什么:

①.Spring能帮我们根据配置文件创建及组装对象之间的依赖关系。
②.Spring 面向切面编程能帮助我们无耦合的实现日志记录,性能统计,安全控制。
③.Spring能非常简单的帮我们管理数据库事务。
④.Spring还提供了与第三方数据访问框架(如Hibernate、JPA)无缝集成,而且自己也提供了一套JDBC访问模板来方便数据库访问。
⑤.Spring还提供与第三方Web(如Struts1、JSF)框架无缝集成,而且自己也提供了一套Spring MVC框架,来方便web层搭建。
⑥.Spring能方便的与Java EE(如Java Mail、任务调度)整合,与更多技术整合(比如缓存框架)。

Spring框架版本:

Spring2.5:
拥抱驱动编程。
支持SimpleJdbcTemplate的命名参数操作。
Spring3.x:
不再支持JDK1.4;
全面支持泛型。
支持SpEL.
支持WebService的OXM。
Spring4.x:
支持Java8,支持JavaEE6规范。
泛型限定式依赖注入。
对Hibernate4的集成和事务提供更好的管理方案。

Spring框架包分析:

现在都提倡使用Maven去下载Spring的jar:
下载地址:http://repo.spring.io/libs-release-local/org/springframework/spring/

spring-framework-4.x.RELEASE:Spring核心组件。
docs: Spring开发、帮助文档。
libs: Spring核心组件的。jar包、源代码、文档。
schema: Spring配置文件的schema约束文件。

spring-framework-3.x.RELEASE-dependencies:Spring依赖的第三方组件。
包含了各大开源组织提供的依赖jar。比如apache common下的:dbcp.jar pool.jar logging.jar

三.IoC和DI简单介绍

IoC:Inverse of Control(控制反转):

读作“控制反转”,更好理解,不是什么技术,而是一种设计思想,好比于MVC。就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。
正控:若调用者需要使用某个对象,其自身就得负责该对象的创建。
反控:调用者只管负责从Spring容器中获取需要使用的对象,不关心对象的创建过程,也就是把创建对象的控制权反转给了Spring框架。
在这里完美地体现了好莱坞法则(Don’t call me ,I’ll call you)。

DI:Dependency Injection(依赖注入):

从字面上分析:
IoC:指将对象的创建权,反转给了Spring容器;
DI :指Spring创建对象的过程中,将对象依赖属性(简单值,集合,对象)通过配置设值给该对象。
IoC和DI其实是同一个概念的不同角度描述,DI相对IoC而言,明确描述了“被注入对象依赖IoC容器配置依赖对象”。

Container

容器,在生活中容器就是一种盛放东西的器皿,从程序设计角度看作是装对象的对象,因为存在对对象的存入、取出等操作,所以容器还要管理对象的生命周期。

四.案例 helloworld

   //准备jar包(核心包)
   spring-beans-4.2.4.RELEASE.jar
   spring-core-4.2.4.RELEASE.jar
   //报错再添加:
   commons.logging-1.2.jar

创建applicationContext.xml

通过import分模块引入各个模块的bean.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.xml-->
    <import resource="classpath:gzcPro/spring/_01helloSpring/hello.xml"></import>
    <import resource="classpath:gzcPro/spring/_02instance/content/App_context.xml"></import>
</beans>

创建hello.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">

    <!-- Ioc: 控制反转  将class交给spring容器管理-->
    <bean id="helloWorld" class="gzcPro.spring._01helloSpring.HelloWorld">
        <!--DI:依赖注入-->
        <property name="name" value="桂志超"></property>
    </bean>
</beans>

创建App_context.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">

    <!-- Ioc: 控制反转  将class交给spring容器管理  
    lazy-init是否在打开spring容器时就加载  false为不延时加载  true为延时加载  
    一般默认为false启动初始化所有的bean 不写-->
    <bean id="someBean" class="gzcPro.spring._02instance.SomeBean" lazy-init="false">
    </bean>

</beans>

创建HelloWorld.java

package gzcPro.spring._01helloSpring;

import lombok.*;

/**
 * Created by Administrator on 2019/8/1.
 */

@AllArgsConstructor
@NoArgsConstructor
@ToString
@Setter
@Getter
public class HelloWorld {
    private String name;

    public void sayHello(){
        System.out.println("hello:"+ name);
    }
}

创建SomeBean.java

package gzcPro.spring._02instance;

import lombok.*;

/**
 * Created by Administrator on 2019/8/1.
 */
@ToString
@Setter
@Getter
public class SomeBean {
    public SomeBean(){
        System.out.println("bean被创建了");
    }
}

创建测试代码APP.java

 @Test
    public void Ioc(){

        //加载spring容器配置文件
        Resource resource = new ClassPathResource("applicationContext.xml");
        //启动spring容器
        BeanFactory factory=new XmlBeanFactory(resource);
        //way-01 getBean 需要强转(不推荐) 容器中可能有多个相同id
        //HelloWorld helloWorld=(HelloWorld) factory.getBean("helloWorld");
        //way-02 getBean 容器中可能有多个相同class(不推荐)
        //HelloWorld helloWorld= factory.getBean(HelloWorld.class);
        //way-03 getBean (推荐)
        HelloWorld helloWorld= factory.getBean("helloWorld",HelloWorld.class);

        System.out.println(helloWorld);
    }

bean被创建了
HelloWorld(name=桂志超)

applicationContext.xml 中包含App_context.xml
如下模拟所说,会获取空的构造函数,所以下面代码执行了

 public SomeBean(){ //空的构造函数
        System.out.println("bean被创建了");
    }

Spring管理bean的原理:

什么是BeanFactory:
Spring最基本的接口,表示Spring容器——生产bean对象的工厂,负责配置,创建和管理bean。
备注:bean是Spring管理的单位,在Spring中一切都是bean.

深入Spring管理bean的原理:

1、通过Resource对象加载配置文件;
2、解析配置文件,得到指定名称的bean;
3、解析bean元素,id作为bean的名字,class用于反射得到bean的实例:

模拟spring容器实现:

//模拟spring容器实现
    @Test
    public void test() throws Exception {
        //模拟xml数据
        String className = "gzcPro.spring._01helloSpring.HelloWorld";
        String propertyName = "name";
        String propertyValue = "桂志超";
        //模拟spring操作:IOC 内省
        Class<?> aClass = Class.forName(className);
        //获取空参构造器
        Constructor<?> declaredConstructors = aClass.getDeclaredConstructor();
        //允许访问
        declaredConstructors.setAccessible(true);

        HelloWorld helloWorld = (HelloWorld) declaredConstructors.newInstance();
        //通过内省 赋值DI
        BeanInfo beanInfo = Introspector.getBeanInfo(aClass, Object.class);
        //获取描述器
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor pd:propertyDescriptors) {
            if (propertyName.equals(pd.getName())){
                pd.getWriteMethod().invoke(helloWorld,propertyValue);
            }
        }
        System.out.println(helloWorld);
        helloWorld.sayHello();
    }

HelloWorld(name=桂志超)
hello:桂志超

说到底,Ioc就是在配置文件中 添加bean对象, DI就是在对象在添加属性值

单元测试说明

    junit4.12  hamcrest-core-1.3.jar
			   junit-4.12.jar
			   
    spring-test-4.2.4.RELEASE.jar. //单元测试
    spring-context-4.2.4.RELEASE.jar. //
    spring-aop-4.2.4.RELEASE.jar. //
    spring-expression-4.2.4.RELEASE.jar. //
    将 spring容器拿出来,不用每次都创建spring容器
/**
 * Created by gzc on 2019/8/1.
 */
@RunWith(SpringJUnit4ClassRunner.class)//引入spring单元测试
@ContextConfiguration("classpath:applicationContext.xml")//引入配置文件
public class App {

    //自动从spring容器中获取这个bean
    @Autowired
    private HelloWorld helloWorld;

    @Test
    public void  test1() throws Exception {
        System.out.println(helloWorld);
    }
}

@Autowired 自动从spring容器中获取这个bean(bean是存在的)

@RunWith(SpringJUnit4ClassRunner.class)//引入spring单元测试
@ContextConfiguration(“classpath:applicationContext.xml”)//引入配置文件
@Autowired
private HelloWorld helloWorld;
取代了----------->
//加载spring容器配置文件
Resource resource = new ClassPathResource(“applicationContext.xml”);
//启动spring容器
BeanFactory factory=new XmlBeanFactory(resource);
HelloWorld helloWorld= factory.getBean(“helloWorld”,HelloWorld.class);

IoC容器:BeanFactory和ApplicationContext对象

BeanFactory:是Spring中最底层的接口,只提供了最简单的IoC功能,负责配置,创建和管理bean。
在应用中,一般不使用BeanFactory,而推荐使用ApplicationContext(应用上下文),原因如下。
BeanFactory和ApplicationContext的区别:
1、ApplicationContext继承了BeanFactory,拥有了基本的IoC功能;
2、除此之外,ApplicationContext还提供了以下的功能:
①、支持国际化;
②、支持消息机制;
③、支持统一的资源加载;
④、支持AOP功能;

package gzcPro.spring._02instance.content;

import ...

/**
 * Created by gzc on 2019/8/1.
 */
//@RunWith(SpringJUnit4ClassRunner.class)//引入单元测试
//@ContextConfiguration("classpath:applicationContext.xml")//引入配置文件
public class App {

    //自动从spring容器中获取这个bean
//    @Autowired
//    private ApplicationContext context;


    @Test
    public void testAppCtx(){
        ApplicationContext context = new ClassPathXmlApplicationContext("gzcPro/spring/_02instance/content/App_context.xml");
        SomeBean someBean1=context.getBean("someBean",SomeBean.class);
        SomeBean someBean2=context.getBean("someBean",SomeBean.class);
        System.out.println(someBean1==someBean2);
    }
}

ApplicationContext context = new ClassPathXmlApplicationContext(“gzcPro/spring/_02instance/content/App_context.xml”);
开启App_context.xml spring容器中的所有bean
---------------------------------------------------》换成
@ContextConfiguration(“App_context.xml”)//引入配置文件
或者(@ContextConfiguration(“classpath:applicationContext.xml”)//引入配置文件)
@Autowired
private ApplicationContext context;

/**
 * Created by gzc on 2019/8/1.
 */
@RunWith(SpringJUnit4ClassRunner.class)//引入单元测试
//@ContextConfiguration("classpath:applicationContext.xml")//引入配置文件
@ContextConfiguration("App_context.xml")//引入配置文件
public class App {

    //自动从spring容器中获取这个bean
    @Autowired
    private ApplicationContext context;


    @Test
    public void testAppCtx(){
        SomeBean someBean1=context.getBean("someBean",SomeBean.class);
        SomeBean someBean2=context.getBean("someBean",SomeBean.class);
        System.out.println(someBean1==someBean2);
    }
}
发布了6 篇原创文章 · 获赞 0 · 访问量 184

猜你喜欢

转载自blog.csdn.net/hero_chao/article/details/103842562