Spring学习总结(一)——对IOC的理解和配置使用(基于XML和基于注解)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40348465/article/details/84893186

一、Spring框架概述    

Spring是一个非常活跃的开源框架, 它是一个基于IOC和AOP来构架多层JavaEE系统的框架,它的主要目地是简化企业开发。

Spring以一种非侵入式的方式来管理你的代码, Spring提倡“最少侵入”,这也就意味着你可以适当的时候安装或卸载Spring。

Spring采用独立的模块式开发,这样可以有选择的使用其中的模块,降低了业务对象的复杂性和组件之间的耦合性。

Spring的AOP支持允许将一些通用的功能,如:性能分析,事务管理,日志记录等进行集中的模块处理,提高了复用,降低了和业务功能的耦合。

Spring支持和ORM层以及MVC层框架的整合,简化了对其他层次的访问。

Spring给开发者带来的好处:降低组件之间的耦合度,实现软件各层之间的解耦

不用关心事务API就可以执行数据库事务;

不用关心远程API就可以使用远程操作;

不用关心JMX API就可以进行管理操作;

不用关心JMS API就可以进行消息处理。

扫描二维码关注公众号,回复: 5656765 查看本文章

①JMX,Java Management eXtension,Java管理扩展,是一个为应用程序、设备、系统等植入管理功能的框架。JMX可以跨越一系列异构操作系统平台、系统体系结构和网络传输协议,灵活的开发无缝集成的系统、网络和服务管理应用。

②JMS,Java Message Service,Java消息服务,是Java平台上有关面向消息中间件(MOM)的技术规范,它便于消息系统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口简化企业应用的开发。

下载

Spring官网: http://spring.io

下载地址: http://repo.springsource.org/libs-release-local/org/springframework/spring/

1.1、Spring框架的特征和功能

轻量:从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。

控制反转Ioc:Spring通过一种称作控制反转(IoC)的技术促进了低耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。

面向切面Aop:Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。

容器:Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。

框架:Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。

MVC:Spring的作用是整合,但不仅仅限于整合,Spring 框架可以被看做是一个企业解决方案级别的框架,Spring MVC是一个非常受欢迎的轻量级Web框架。

所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。

1.2、Spring的组成

Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式

组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:

  • 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
  • Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
  • Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
  • Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
  • Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
  • Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
  • Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

Spring 框架的功能可以用在任何 J2EE 服务器中,大多数功能也适用于不受管理的环境。Spring 的核心要点是:支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同 J2EE 环境 (Web 或 EJB)、独立应用程序、测试环境之间重用。

1.3、Spring Boot与Spring Cloud

Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务,Spring Cloud是一个基于Spring Boot实现的云应用开发工具;Spring Boot专注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架;Spring Boot使用了约束优于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置,Spring Cloud很大的一部分是基于Spring Boot来实现,Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring Boot,属于依赖的关系。

SpringBoot在SpringClound中起到了承上启下的作用,如果你要学习SpringCloud必须要学习SpringBoot。

二、IOC简介

   IOC(Inversion of Control,即控制反转),是一种设计思想,IOC其实就是包含并管理应用对象的配置和生命周期,你可以配置你的每个bean如何被创建,也可以配置每个bean是只有一个实例,还是每次需要时都生成一个新的实例,以及它们是如何相互关联的。

DI(Dependency injection,即依赖注入)是IOC的一种常见的方式,是指应用在运行期,由外部容器(Spring容器)动态地将依赖对象注入到另一个对象中。

IOC的思想最核心的地方在于,资源不由使用资源的双方管理,而由不使用资源的第三方管理,这可以带来很多好处:

   第一,资源集中管理,实现资源的可配置和易管理。

   第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度。

   IOC是Spring框架的核心内容,使用多种方式完美的实现了IOC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。

   采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

以上部分内容借鉴于博客:https://www.cnblogs.com/best/p/5727935.html#_label3

补充:

BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等

ApplicationContext:通过API文档可以知道,ApplicationContext是BeanFactory的子接口。大部分程序都不会使用BeanFactory作为容器接口(通常JavaSE应用或者手机应用使用),而是使用ApplicationContext作为Spring的容器接口,它增强了BeanFactory的功能。

ApplicationContext的实现有四种方式:

FileSystemXmlApplicationContext:加载配置文件的时候采用的是项目的路径。

ClassPathXmlApplicationContext:加载配置文件的时候根据ClassPath位置。

XmlWebApplicationContext:在Web环境下初始化监听器的时候会加载该类。

AnnotationConfigApplicationContext:根据注解的方式启动Spring 容器。

从上下文中获取Bean的常用方法有:

  Object getBean(String name);//通过id的名称获取,需要强制转换

  T getBean(Class<T> requiredType);//根据类型获取Bean

  T getBean(String name, Class<T> requiredType);//根据id的名称获取到指定类型的Bean

1.使用XML方式配置IOC

beans其他常用属性:

 (1)default-lazy-init:指定该beans元素下配置的所有的bean都默认延迟初始化(没有使用到不进行实例化);

 (2)default-autowire:指定该beans下配置的所有的bean默认是自动装配的;

 (3)default-init-method:指定该beans下配置的所有的bean默认的初始方法;

 (4)default-destroy-method:指定beans元素下配置的所有的bean默认的回收方法。

注意:在beans下配置的属性是全局属性,在每个bean元素下也是可以单独指定的,只是要把default去掉即可(default-autowire对应为autowire)。bean中指定的属性只能在当前的bean元素上起作用,当二者出现冲突的时候会优先使用bean下指定的属性。

bean的其他常用属性:

(1)abstract以及parent: abstract以及parent是搭配使用的,如果bean定义了属性abstact=true,那么这个类就无法通过Spring容器拿到,而是作为一个模板存在。有点类似于设计模式中的模板方法。这个bean对应的类它定义的属性,方法可以被复用。通过Parent属性在子类中可以指向被abstract定义的bean。
(2)singleton(默认为“true”):定义Bean是否是Singleton(单例)。如果设为“true”,则在BeanFactory作用范围内,只维护此Bean的一个实例。如果设为“flase”,Bean将是Prototype(原型)状态,BeanFactory将为每次Bean请求创建一个新的Bean实例。
(3)lazy-init(默认为“default”):用来定义这个Bean是否实现延迟初始化。如果为“true”,它将在BeanFactory启动时初始化所有的SingletonBean。反之,如果为“false”,它只在Bean请求时才开始创建SingletonBean。

(4)autowire(自动装配,默认为“default”):它定义了Bean的自动装载方式。

        1、“no”:不使用自动装配功能。

        2、“byName”:通过Bean的属性名实现自动装配。

        3、“byType”:通过Bean的类型实现自动装配。

       4、“constructor”:类似于byType,但它是用于构造函数的参数的自动组装。

       5、“autodetect”:通过Bean类的反省机制(introspection)决定是使用constructor还是byType方式进行自动装配。

(5)depends-on(依赖对象):这个Bean在初始化时依赖的对象,这个对象会在这个Bean初始化之前创建。

(6)init-method:用来定义Bean的初始化方法,它会在Bean组装之后调用。它必须是一个无参数的方法。

         init-method在Bean的属性被初始化之后执行,一般做初始化数据

(7)destroy-method:用来定义Bean的销毁方法,它在BeanFactory关闭时调用。同样,它也必须是一个无参数的方法。它只能应用于singletonBean。

        destroy-method在Bean被销毁之前进行执行,一般作为清理资源

Bean的生命周期如下:

     

 (8)factory-method:定义创建该Bean对象的工厂方法。它用于下面的“factory-bean”,表示这个Bean是通过工厂方法创建。此时,“class”属性失效。

(9)factory-bean:定义创建该Bean对象的工厂类。如果使用了“factory-bean”则“class”属性失效。

  (10)scope,用来指定该bean的作用域,其值有:

          1、singleton: 在这个spring容器里面只有一个实例;

          2、prototype: 每一次请求都会创建一个新的bean实例;

          3、request: 每一次请求创建一个新的实例,在Web Application中有效;

          4、session: 每一个session创建一个新的实例,在Web Application中有效;

          5、global-session: 对每一个global HTTP session创建一个新的实例,在Web Application中有效。

     作用域中比较常用的是singleton和prototype,没有配置作用域的情况下Bean的默认作用域是singleton的。Spring容器对于singleton和prototype进行管理是不一样的。如果Bean是singleton的时候Spring的容器会进行跟踪Bean实例的状态,负责维护Bean实例的生命周期的行为;如果Bean被设置为prototype作用域时,Spring容器仅仅只是调用构造函数进行创建一个实例,一旦创建成功容器就不再进行跟踪实例,也不会维护Bean实例的状态。

     单例的在系统中进行只需要创建一次就能重复的使用,会减少系统在创建实例和回收实例时的资源开销。

依赖注入的两种方式:

  (1).设值注入:

需要在对应的实体类中有相应的Setter方法

za

  (2).构造注入:

   需要在对应的实体类中有相应的构造函数

 使用List、Set、Map:

<!-- List、Map、Set -->
	<!-- 配置一个员工bean -->
	<bean id="tempEmp" class="com.springstudy.pojo.Employee">
		<property name="empId" value="1003"></property>
		<property name="empName" value="王五"></property>
		<property name="age" value="20"></property>
	</bean>

	<!-- 配置一个部门bean -->
	<bean id="dept" class="com.springstudy.pojo.Department">
		<!-- java.util.List -->
		<property name="empList">
			<list>
				<ref bean="tempEmp" />
				<bean class="com.springstudy.pojo.Employee">
					<property name="empId" value="1004"></property>
					<property name="empName" value="赵六"></property>
					<property name="age" value="20"></property>
				</bean>
			</list>
		</property>

		<!-- java.util.Set -->
		<property name="empSet">
			<set>
				<value>1</value>
				<ref bean="tempEmp" />
				<bean class="com.springstudy.pojo.Employee">
					<property name="empId" value="1005"></property>
					<property name="empName" value="赵六"></property>
					<property name="age" value="20"></property>
				</bean>
			</set>
		</property>

		<!-- java.util.Map -->
		<property name="empMap">
			<map>
				<entry key="Key1" value="1" />
				<entry key="Key2" value-ref="tempEmp" />
				<entry key="Key3">
					<bean class="com.springstudy.pojo.Employee">
						<property name="empId" value="1006"></property>
						<property name="empName" value="赵六"></property>
						<property name="age" value="20"></property>
					</bean>
				</entry>
			</map>
		</property>
	</bean>

自动绑定:

也可以直接在某个bean中单独设置,如:

2.基于Annotation的注解方式:

    常用的注解:

  (1)@Component:用来标注任何一个普通的Java类;如:

@Component
public class Employee {
 ...
}

  (2)@Controller:用来标注一个控制类(Struts的Action或者Springwebmvc的Controller);  如:

@Controller
public class LoginServlet {
 ...
}

  (3)@Service:用来标注一个业务逻辑的Java类;如:      

@Service
public class EmployeeServiceImpl implements IEmployeeService {
...
}

  (4)@Repository:标注一个DAO的Java类; 如:

@Repository
public class EmployeeDaoImpl implements IEmployeeDao {
 ...
}

  (5)@AutoWired:   表示告诉Spring ,这里是 一个属性,自动注入;如:   

@Service
public class EmployeeServiceImpl implements IEmployeeService {
	@Autowired
	private IEmployeeDao employeeDao;
    ...
}

    补充:@Autowired(required=false):表示忽略当前要注入的bean,若有直接注入,若没有则跳过(此时也不会报错)。

 

(6) @Resource: 依赖资源,依赖对象,不是Spring的注解;如:  

@Repository("employeeDaoImpl_Test")
public class EmployeeDaoImpl implements IEmployeeDao {
...
}

 

@Service
public class EmployeeServiceImpl implements IEmployeeService {
	//@Autowired
	@Resource(name="employeeDaoImpl_Test")
	private IEmployeeDao employeeDao;
    ...
}

(7)@Value :  属性值 的注入,如:

   

@Component
public class Employee {
	private int empId;
	@Value("张三")
	private String empName;
	@Value("20")
	private int age;
    ...
}

   当上面的注解配置完成之后,可以方式一:在XML配置文件中自动扫描和绑定,如:

    方式二:基于注解的零xml配置:

   (8)@Configuration: 用于指定当前类是一个spring配置类,当创建容器时会从该类上加载注解。获取容器时需要使用,使用@Configuration注解表示这个一个配置类,等同于xml配置中xml文件。

  (9)@ComponentScan:用于指定spring在初始化容器时要扫描的包。

  基于注解的零XML配置示例:


//使用@Configuration注解表示这个一个配置类,等同于xml配置中xml文件。
@Configuration

//类似xml配置中的component-scan,我们可以配置针对特别package的扫描配置,自动将包内@Component、@Service 等注解的bean类给扫描出来,注入到容器中。用法如下:
@ComponentScan(basePackages = "com.springstudy")
public class SpringConfiguration {

}

  

public class SpringTest {
	private static ApplicationContext ac;

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		if(ac==null) {
			//在纯java类配置的场景中,AnnotationConfigApplicationContext承担了同样地构建容器实例的角色
			ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
		}
	}

	@Test
	public void test() {
		IEmployeeService empService = ac.getBean("employeeServiceImpl",EmployeeServiceImpl.class);
	    Employee emp = empService.getEmployee();
	    System.out.println(emp);
	}

}

   其他常用的注解:

     (10)@Bean:该注解只能写在方法上,将方法的返回值作为一个bean,并且放入spring容器。 

               其属性name:可以给当前@Bean注解方法创建的对象指定一个名称。

@Bean(name = {"jdbcTemplate"})
public JdbcTemplate createJdbcTemplate(@Qualifier(value = "dataSource") DataSource dataSource) {
    return new JdbcTemplate(dataSource);
}
 

     (11)@PropertySource:用于加载.properties文件中的配置。如:

     

@PropertySource(value = {"classpath:jdbc.properties"})
public class JdbcConfig {
    @Value(value = "${jdbc.driverClass}")
    private String driverClassName;
    @Value(value = "${jdbc.url}")
    private String url;
    @Value(value = "${jdbc.username}")
    private String username;
    @Value(value = "${jdbc.password}")
    private String password;
 
    @Bean(name = {"jdbcTemplate"})
    public JdbcTemplate createJdbcTemplate(@Qualifier(value = "dataSource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
 
    @Bean(name = {"dataSource"})
    public DataSource createDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}

       (12)@Import:用于导入其他配置类。

   

@Configuration
@ComponentScan(value = {"com.springstudy"})
@Import(value = JdbcConfig.class)
public class SpringConfiguration {
 
}

猜你喜欢

转载自blog.csdn.net/qq_40348465/article/details/84893186