Spring

本文详细介绍了Spring框架的分层架构、解耦开发、AOP编程、事务管理、测试支持、与其他框架集成以及依赖管理和配置。涵盖了核心组件、bean实例化、注解注入和生命周期管理等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 . 概述

Spring 是一个开源框架,框架的主要优势之一就是其分层架构,Spring 使用基本的 JavaBean 来完成以前只可能由 EJB 完成的事情。然而,Spring 的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何 Java 应用都可以从 Spring 中受益。Spring 的核心是控制反转(IOC)和面向切面(AOP)。简单来说,Spring 是一个分层的  轻量级开源框架。

2. 特点

  1. 方便解耦,简化开发
  2. Spring 就是一个大工厂,可以将所有对象创建和依赖关系维护,交给 Spring 管理
  3. AOP 编程的支持,Spring 提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
  4. 声明式事务的支持只需要通过配置就可以完成对事务的管理,
  5. 而无需手动编程方便程序的测试,Spring 对 Junit4 支持,可以通过注解方便的测试 Spring 程序
  6. 方便集成各种优秀框架,Spring  不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz 等)的直接支持
  7. 降低 JavaEE API 的使用难度,Spring 对 JavaEE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等),都提供了封装,使这些 API 应用难度大大降低

3. 依赖

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <spring.version>4.2.5.RELEASE</spring.version>
    </properties>   

			<!--Spring核心基础依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--日志相关-->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <!--测试相关-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

4. 配置文件

配置文件的名字可以任意设置,建议设置为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">
 
</beans>

5. 添加相应的模块

在项目中添加dao、model、service层代码

6. 将bean的实例化交给Spring

<bean name="userDao" class="com.tledu.spring.dao.impl.UserDaoImpl" />
<!--name 属性名字/ref 引用的bean的名字-->
<bean id="userService" class="com.tledu.spring.service.UserService">
	<property name="userDao"  ref="userDao" />
</bean>

7. 通过构造方法注入

 <bean name="userDao" class="com.tledu.spring.dao.impl.UserDaoImpl" />
    <bean id="userService" class="com.tledu.spring.service.UserService">
        <constructor-arg ref="userDao"/>
    </bean>

8. 普通属性注入

	<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl">
	<!-- 如果不是指向对象,直接用value设置值就行 -->
		<property name="daoId" value="82"></property>
		<property name="daoStatus" value="good"></property>
	</bean>

9. scope

对象在spring容器(IOC容器)中的生命周期

9.1 singleton  prototype

    <!--  singleton:单例模式    prototype:非单例模式-->
    <bean name="userService2" class="com.grp.service.impl.UserServiceImpl2" scope="prototype">
        <constructor-arg ref="userDao"/>
    </bean>

 9.2 配置scope方式

<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl">
  <!-- 如果不是指向对象,直接用value设置值就行 -->
  <property name="daoId" value="82"></property>
  <property name="daoStatus" value="good"></property>
	</bean >
	<!-- scope singleton : 单例 只创建一个,默认就是 
		prototype : 每一次getBean 都会创建一个新的实例化对象  
  request,session : 需要特殊环境支持 -->
	<bean id="userService" class="com.tledu.zrz.service.UserService"
  scope="singleton">
  <!-- 构造方法注入 -->
  <constructor-arg>
  	<ref bean="userDao" />
  </constructor-arg>
</bean>

9.3 集合注入

<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl">
  <property name="lists" >
  	<list>
    	<value>1</value>
    	<value>2</value>
  	</list>
  </property>
  <property name="sets" >
  <!-- set不可重复,重复不添加,所以只有第一个三 -->
  	<set>
    	<value>3</value>
    	<value>3</value>
    	<value>5</value>
    	<value>4</value>
  	</set>
  </property>
  <property name="maps">
  <!-- mapkey不可重复,重复key不添加,value覆盖 -->
  	<map>
    	<entry key="1"  value="2"></entry>
    	<entry key="1"  value="3"></entry>
    	<entry key="2"  value="2"></entry>
  	</map>
  </property>
	</bean>

	<bean id="userService" class="com.tledu.zrz.service.UserService"
  scope="singleton">
  <!-- 构造方法注入 -->
  <constructor-arg>
  	<ref bean="userDao" />
  </constructor-arg>
	</bean>

10. 自动装配

10.1 byName

byName是根据setter方法名字进行匹配,如果找不到,就不赋值

如 setUserDao 方法  就会找userDao,如果 bean的ID为 UserDao 也一样找不到,区分大小写

设置方式

<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl">

</bean>

<bean id="userService" class="com.tledu.zrz.service.UserService"  

 autowire="byName">

</bean>

10.2 byType

byType是根据setter方法的参数列表中的数据类型进行匹配,如果beans.xml中出现了多个相同类型的对象,就会报错

如 setUserDao(UserDao userDao) 方法  就会找UserDao,如果是接口,就找对应的实现类对象

设置方式

<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl">

</bean>

<bean id="userService" class="com.tledu.zrz.service.UserService"  

 autowire="byType">

</bean>

11. 生命周期

UserService中提供对应的方法

public void init(){
  System.out.println("init--------");
	}
	public void destroy(){
  System.out.println("destroy----------");
	}
	public UserService() {
  System.out.println("service构造方法");
}

配置文件

<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl" >
	</bean>
	<!--  
  init-method : 用于设置初始化的方法
  destory-method : 用于设置销毁资源的方法
  -->
	<bean id="userService" class="com.tledu.zrz.service.UserService"  
  autowire="byName"   init-method="init" destroy-method="destroy"  >
	</bean>

测试

@Test
public void testAdd() {
  ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
    "beans.xml");
  // userService是bean的id或name
   UserService userService = (UserService) applicationContext
   .getBean("userService");
  // // userService.add(null);
   System.out.println(userService.getUserDao());
  // 销毁Spring容器
   applicationContext.destroy();
}

12 . 迟加载

相关类

public UserDaoImpl(){
  System.out.println("Dao构造方法");
}
public UserService() {
  System.out.println("service构造方法");
}

配置文件

<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl" >
<bean id="userService" class="com.tledu.zrz.service.UserService"  scope="prototype"
  	autowire="byName"   init-method="init" destroy-method="destroy" lazy-init="true"  >
</bean>

测试

@Test
	public void testAdd() {
  ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
    "beans.xml");
}

13 IOC注解

13.1 XML和注解的区别

13.1.1 XML配置

优点有:

XML配置方式进一步降低了耦合,使得应用更加容易扩展,即使对配置文件进一步修改也不需要工程进行修改和重新编译。
在处理大的业务量的时候,用XML配置应该更加好一些。因为XML更加清晰的表明了各个对象之间的关系,各个业务类之间的调用。同时spring的相关配置也能一目了然。

缺点有:

配置文件读取和解析需要花费一定的时间,配置文件过多的时候难以管理,无法对配置的正确性进行校验,增加了测试难度。

13.1.2 annotation配置

优点有:  

在class文件中,可以降低维护成本,annotation的配置机制很明显简单  
不需要第三方的解析工具,利用java反射技术就可以完成任务  
编辑期可以验证正确性,查错变得容易  
提高开发效率  
缺点有:  

如果需要对于annotation进行修改,那么要重新编译整个工程  
业务类之间的关系不如XML配置那样容易把握。  
如果在程序中annotation比较多,直接影响代码质量,对于代码的简洁度有一定的影响

13.2 注解注入使用步骤

13.2.1 Autowired

13.2.1.1 导包

<dependency>

  <groupId>org.springframework</groupId>

  <artifactId>spring-aop</artifactId>

        <version>${spring.version}</version>

</dependency>

13.2.1.2 开启注解的支持

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

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

        xsi:schemaLocation="http://www.springframework.org/schema/beans

       http://www.springframework.org/schema/beans/spring-beans.xsd

       http://www.springframework.org/schema/context

       http://www.springframework.org/schema/context/spring-context.xsd">

        <!-- 引入注解约束 -->

        <!-- 使用注解形式自动装配 -->

        <context:annotation-config />

        <context:component-scan base-package="需要扫描的包名"/>

</beans>

13.2.1.3 业务类

//类名上添加Component注解

@Component

public class UserService {

    private IUserDao userDao;

//需要注入的变量上添加@Autowired

    @Autowired

    public void setUserDao(IUserDao userDao) {

        this.userDao = userDao;

}

}

//获取bean时需要类名小驼峰

application.getBean("addressServiceImpl"

13.2.1.4 知识点

@Autowired(自动封装)

该注解可以加在set方法上或者直接加载属性上,如果写在setter方法上,就会通过setter方法进行注入,如果写在变量上,就直接通过反射设置变量的值,不经过setter方法。

注入时,会从spring容器中,找到一个和这个属性数据类型匹配的实例化对象注入进来,默认使用byType,根据类型匹配。

如果只能找到一个这个数据类型的对象的时候,就直接注入该对象。

如果找到了多个同一个类型的对象的时候,就会自动更改为byName来进行匹配,根据set方法对应的参数列表的局部变量名来匹配。

@Qualifier :  

以指定名字进行匹配 
 

private IUserDao userDao;

@Autowired

public void setUserDao(@Qualifier(“userDao2”)IUserDao userDao){};

//这时候就不会按照userDao来进行匹配了,而是强制使用userDao2来进行比配,也就不会按照类型匹配了

13.2.1.5 配置文件

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

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

        xsi:schemaLocation="http://www.springframework.org/schema/beans

       http://www.springframework.org/schema/beans/spring-beans.xsd

       http://www.springframework.org/schema/context

       http://www.springframework.org/schema/context/spring-context.xsd">

        <!-- 引入注解约束 -->

        <!-- 使用注解形式自动装配 -->

        <context:annotation-config />

        <bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl">

  <property name="daoId" value="1"></property>

        </bean>

  <bean name="userDao2" class="com.tledu.zrz.dao.impl.UserDaoImpl">

  <property name="daoId" value="2"></property>

        </bean>

        <bean id="userService" class="com.tledu.zrz.service.UserService">

        </bean>

</beans>

13.2.2 Resource

Resource这个注解是javaEE的,在javax包下,所以不需要导入其他jar包

@Resource默认使用byName的方式,按照名字匹配,可以写在setter方法上也可以写在变量上

先匹配set方法的名字,匹配不上再匹配方法参数列表的名字

如果还是匹配不上就会转换为byType,根据类型匹配

当然我们也可以指定名字

@Resource(name=”userDao”)  

就相当于 Autowired和Qualifier 一起使用

相关的还有一个 @Inject 根据type匹配,通过named指定名字,自行学习  

导包javax.inject.Inject
 

13.2.2.1业务类

@Resource(name="userDao")

  public void setUserDao(UserDao userDao) {

         System.out.println("--------------");

         this.userDao2 = userDao;

        }

13.3 注解实例化使用步骤

13.3.1配置文件

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"

        xsi:schemaLocation="http://www.springframework.org/schema/beans

       http://www.springframework.org/schema/beans/spring-beans.xsd

       http://www.springframework.org/schema/context

       http://www.springframework.org/schema/context/spring-context.xsd">

        <!-- 使用注解形式自动装配 -->

        <context:annotation-config />

        <!-- 使用注解形式实例化对象 -->

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

</beans>

13.3.2业务类

所有需要实例化对象的类上面都加上@Component  

默认是以类名首字母小写作为名字进行存储

可以使用@Component(“xxx”) 或者@Component(value=”xxx”)来设置名字

@Component(value="userDao")

public class UserDaoImpl implements UserDao {

@Component

public class User {

@Component("userService")

public class UserService {

13.3.3 注解分类

@Controller :WEB 层 ,就是和页面交互的类

@Service :业务层 ,主要处理逻辑

@Repository :持久层 ,就是Dao操作数据库

这三个注解是为了让标注类本身的用途清晰,Spring 在后续版本会对其增强  

@Component: 最普通的组件,可以被注入到spring容器进行管理

@Value :用于注入普通类型. 可以写在变量上和setter方法上

@Autowired :自动装配,上面描述比较详细,可以参照上面

@Qualifier:强制使用名称注入.  

@Resource 相当于: @Autowired 和@Qualifier 一起使用

@Scope: 设置对象在spring容器中的生命周期

取值 :  

singleton:单例  

prototype:多例

@PostConstruct :相当于 init-method  

@PreDestroy :相当于 destroy-method  

13.3.4注解的区别

@Component 最普通的组件,可以被注入到spring容器进行管理

@Repository 作用于持久层

@Service 作用于业务逻辑层

@Controller 作用于表现层(spring-mvc的注解)

13.4新注解

13.4.1Configuration

作用: 用于指定当前类是一个 spring 配置类,当创建容器时会从该类上加载注解。获取容器时需要使用AnnotationApplicationContext(有@Configuration 注解的类.class)。

属性: value:用于指定配置类的字节码
 

package com.tledu.zrz.config;

import org.springframework.context.annotation.Configuration;

@Configuration

public class SpringConfiguration {

}

10.4.2ComponentScan

作用: 用于指定 spring 在初始化容器时要扫描的包。

作用和在 spring 的 xml 配置文件中的: <context:component-scan base-package="com.tledu.zrz.spring"/>是一样的。

属性: basePackages:用于指定要扫描的包。和该注解中的 value 属性作用一样。
 

@Configuration

@ComponentScan("com.tledu.zrz.spring")

public class SpringConfiguration {

}

10.4.3 Bean

作用: 该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。

属性: name:给当前@Bean 注解方法创建的对象指定一个名称(即 bean 的 id)。

10.4.4 PropertySource

作用: 用于加载.properties 文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。

属性: value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath
 

package com.tledu.zrz.config;

import org.apache.commons.dbcp2.BasicDataSource;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

public class JdbcConfig {

        @Value("${jdbc.driver}")

        private String driver;

        @Value("${jdbc.url}")

        private String url;

        @Value("${jdbc.username}")

        private String username;

        @Value("${jdbc.password}")

        private String password;

}

10.4.5  Import

作用: 用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解。当然,写上也没问题。

属性: value[]:用于指定其他配置类的字节码。

@Configuration

@ComponentScan("com.tledu.zrz.spring")

@Import({ JdbcConfig.class})

public class SpringConfiguration {

}

// jdbc的配置

@Configuration

@PropertySource("classpath:jdbc.properties")

public class JdbcConfig {}

10.4.6  通过注解获取容器

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值