Spring是一个开源免费的框架和容器,具有轻量级和非侵入式的特点。它支持控制反转(IoC)和面向切面(AOP),同时提供了对事务和其他框架的支持。因此,简单来说,Spring就是一个轻量级的IoC和AOP容器框架。
假设有一个应用程序需要使用数据库连接池进行数据存储操作,使用Spring框架可以将数据库连接池的创建和管理交由Spring容器来完成。这样,程序员只需要在需要使用数据库连接池的地方注入(IoC)一个数据源对象即可,而不用自己手动创建和管理连接池的实例。同时,通过AOP的支持,我们还可以在方法执行前后进行一些额外的处理,比如记录日志或者检查权限等。这样,开发人员就可以更加专注于业务逻辑代码的编写,而不必关心底层的技术细节。
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式 .
Spring核心容器(Core Container):提供了Spring框架最基本的功能,包括IoC和依赖注入(DI),以及AOP等技术支持。其中,其中最重要的组件为BeanFactory和ApplicationContext,它们负责创建和管理对象及其依赖关系。
Spring AOP 模块:提供了面向切面编程(AOP)的支持,可以通过拦截器和切面来实现横向业务逻辑的统一处理,比如日志打印和事务管理等。
Spring DAO / JDBC 模块:提供了对JDBC和ORM的支持,可以让开发人员更加方便地与数据库进行交互,包括数据访问对象(DAO)、JdbcTemplate、SimpleJdbcTemplate等API。
Spring ORM 模块:提供了对流行的ORM框架的集成支持,包括Hibernate、MyBatis等。
Spring Web 模块:提供了创建Web应用程序的支持,包括MVC框架、Web服务、Web安全等相关功能。
Spring Test 模块:提供了对Spring应用程序的测试支持,包括基于JUnit和TestNG的测试框架、Mock对象等。
Spring Integration 模块:提供了企业集成(EAI)和消息驱动的架构(MDA)的支持,可以与JMS、AMQP、FTP等进行集成。
总之,Spring框架提供了一种灵活、可扩展和易于使用的解决方案,可以帮助开发人员更加高效地完成企业级应用程序的开发工作。
Spring框架的每个模块(或组件)的详细内容:
核心容器
核心容器是Spring框架的基础,提供了IoC(控制反转)功能。在核心容器中,BeanFactory是最重要的组件之一,它负责管理应用程序中的所有对象。BeanFactory将应用程序的配置和依赖关系规范与实际的应用程序代码分离开来,从而使应用程序更加灵活和易于维护。
Spring上下文
Spring上下文是一个配置文件,为Spring框架提供上下文信息,包括JNDI、EJB、电子邮件、国际化、校验和调度等企业服务。Spring上下文是应用程序中所有bean的集合,它们以及它们之间的依赖关系由Spring容器进行管理。
Spring AOP
Spring AOP模块通过配置管理特性,直接将面向切面的编程功能集成到了Spring框架中。因此,可以很容易地使Spring框架管理任何支持AOP的对象。Spring AOP模块为基于Spring的应用程序中的对象提供了事务管理服务。通过使用Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。
Spring DAO
Spring DAO是一组数据访问抽象层,包括JDBC DAO和ORM(对象关系映射) DAO。它提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO的面向JDBC的异常遵从通用的DAO异常层次结构,从而使数据访问更加灵活和易于维护。
Spring ORM
Spring ORM模块插入了多个ORM框架,包括JDO、Hibernate和iBatis SQL Map,从而提供了ORM的对象关系工具。所有这些都遵从Spring的通用事务和DAO异常层次结构,从而使数据访问更加灵活和易于维护。
Spring Web模块
Spring Web模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文。因此,Spring框架支持与Jakarta Struts的集成。Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
Spring MVC框架
Spring MVC框架是一个全功能的MVC实现,用于构建Web应用程序。通过策略接口,MVC框架变成为高度可配置的,并且可以容纳大量视图技术,包括JSP、Velocity、Tiles、iText和POI等。Spring MVC框架还提供了处理请求和响应的机制以及执行处理器和适配器的机制,从而使Web开发更加简单和灵活。
Spring Boot和Spring Cloud是两个框架,它们都是由Spring开发的并且都是为了支持微服务架构而生的。
Spring Boot专注于快速、方便集成的单个微服务个体,它使用了约束优于配置的理念,这意味着很多集成方案已经帮你选择好了,默认配置非常合理,能不配置就不配置。Spring Boot可以帮助开发者快速搭建一个可运行的应用程序,并提供各种开箱即用的功能。例如,它可以自动配置数据源、事务管理器、Web框架等等,这些功能不需要开发者自己手动去配置。
Spring Cloud是基于Spring Boot实现的服务治理框架,它关注全局的服务治理,包括服务注册与发现、配置中心、负载均衡、断路器、分布式追踪等等。Spring Cloud为开发者提供了一系列的工具来简化微服务架构下的开发、部署和运维工作。通过Spring Cloud,开发者可以轻松地实现各种复杂的服务治理功能,而不必自己重新开发或者使用第三方库。
在实际项目开发中,Spring Boot通常被用来快速创建单个微服务,而Spring Cloud则被用来构建和管理整个微服务架构。Spring Boot和Spring Cloud可以一起使用,Spring Boot在Spring Cloud中起到了承上启下的作用。如果你要学习Spring Cloud,那么你必须要先学习Spring Boot,因为Spring Cloud很大的一部分是基于Spring Boot来实现的,同时Spring Cloud也依赖于Spring Boot。
IoC基础
// UserDao接口
public interface UserDao {
public void getUser();
}
public class UserDaoImpl implements UserDao {
@Override
public void getUser() {
System.out.println("获取用户数据");
}
}
// UserService的接口
public interface UserService {
public void getUser();
}
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
@Override
public void getUser() {
userDao.getUser();
}
}
@Test
public void test() {
UserService service = new UserServiceImpl();
service.getUser();
}
public class UserDaoMySqlImpl implements UserDao {
@Override
public void getUser() {
System.out.println("MySql获取用户数据");
}
}
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoMySqlImpl();
@Override
public void getUser() {
userDao.getUser();
}
}
public class UserDaoOracleImpl implements UserDao {
@Override
public void getUser() {
System.out.println("Oracle获取用户数据");
}
}
public class UserServiceImpl implements UserService {
private UserDao userDao;
// 利用set实现
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void getUser() {
userDao.getUser();
}
}
控制反转(IoC)是一种设计原则,它的本质在于将程序中对象的创建和对象之间的依赖关系从程序代码中解耦出来。换言之,IoC意味着程序不再控制对象的创建和依赖关系,而是将这些任务交给外部容器或框架处理。
具体来说,IoC的实现通常涉及到依赖注入(DI)技术。依赖注入是指通过构造函数、属性、方法等方式将一个对象所依赖的其他对象注入进去。通过依赖注入,我们可以轻松地替换依赖关系中的任何一个组件,而无需修改程序代码。
总的来说,IoC 的本质在于通过将对象的创建和依赖关系管理转移到外部容器或框架中,使得程序变得更加灵活、可扩展和易于维护。
IoC是Spring框架的核心内容,Spring通过多种方式实现了IoC,其中比较常用的方式包括XML配置、注解和零配置。
在使用XML配置时,我们需要在配置文件中定义Bean(即对象)的创建方式和依赖关系。当程序需要使用这些Bean时,Spring容器会根据配置文件中的信息自动创建对象,并将依赖关系注入到相应的对象中。相对来说,XML配置方式实现IoC更加灵活,可以满足不同场景下的需求。
使用注解实现IoC,可以让代码更加简洁和易于维护。通过在类或方法上添加注解,我们可以告诉Spring容器如何创建并管理这些对象,同时也方便了其他开发人员阅读和理解代码。
而零配置实现IoC,则是指Spring可以根据类路径扫描机制,自动创建对象并管理依赖关系,从而省略了繁琐的配置步骤。这种方式可以提高开发效率,但可能会影响程序的可维护性,因为没有明确的配置信息。
总的来说,Spring框架通过多种方式完美地实现了IoC,使得程序变得更加灵活、可扩展和易于维护。开发人员可以根据不同的需求选择合适的方式实现IoC。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。
控制反转(Inversion of Control, IoC)是一种设计模式,它将程序中对象的依赖关系从程序代码中剥离出来,交给IoC容器进行管理。这样做的好处是,程序员不再需要手动创建和管理对象之间的依赖关系,让程序更加灵活、可扩展和易于维护。
在Spring框架中,控制反转是通过IoC容器实现的。IoC容器负责实例化Bean,并将Bean的依赖注入到其他Bean中。Spring支持两种方式配置Bean:XML方式和注解方式。
使用XML方式配置Bean时,需要在XML文件中定义Bean的配置信息,包括Bean的类名、属性等信息。这种方式需要程序员手动编写XML文件,并且需要遵循特定的XML结构。
而使用注解方式配置Bean时,则是在Bean的实现类中使用注解定义Bean的配置信息。通过在类上添加注解,告诉Spring容器该类是一个Bean,并指定其相关的属性、依赖等信息。这种方式相对于XML方式更加灵活,简洁易懂,并且能够减少重复的代码,提高开发效率。
控制反转的核心思想是将对象的创建和依赖注入交由IoC容器处理,Spring框架通过依赖注入实现了控制反转,可以更加灵活地管理Bean之间的依赖关系,提高了程序的可扩展性和维护性。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
spring 需要导入commons-logging进行日志记录 . 我们利用maven , 他会自动下载对应的依赖项 .
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.10.RELEASE</version>
</dependency>
public class Hello {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("Hello,"+ name );
}
}
<?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就是java对象 , 由Spring创建和管理-->
<bean id="hello" class="com.da.pojo.Hello">
<property name="name" value="Spring"/>
</bean>
</beans>
public class User {
private String name;
public User() {
System.out.println("user无参构造方法");
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("name="+ name );
}
}
<?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="user" class="com.da.pojo.User">
<property name="name" value="da"/>
</bean>
</beans>
alias 设置别名 , 为bean设置别名 , 可以设置多个别名
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
<bean id="student" class="com.da.pojo.Student">
<property name="name" value="da"/>
</bean>
@Component //将这个类标注为Spring的一个组件,放到容器中!
public class Dog {
public String name = "dog";
}
@Configuration //代表这是一个配置类
public class MyConfig {
@Bean //通过方法注册一个bean,这里的返回值就Bean的类型,方法名就是bean的id!
public Dog dog(){
return new Dog();
}
}
AOP的底层机制就是动态代理!
代理模式:
静态代理
动态代理
AOP(面向切面编程)的核心机制之一是动态代理。在Java应用程序中,代理模式是实现动态代理的一种常见方式。
代理模式是一种设计模式,它允许一个对象作为另一个对象的接口进行访问。代理对象可以充当客户端与目标对象之间的中介,从而控制对目标对象的访问。
静态代理与动态代理是代理模式的两种实现方式。静态代理需要手动编写代理类代码,而动态代理则在运行时生成代理类。动态代理可以更加灵活地适应不同的需求,并且可以减少冗余的代理类代码。
在Java中,动态代理通常使用Java反射来实现。通过动态代理,可以在不改变目标对象的代码的情况下,实现对目标对象的增强。例如,可以在方法执行前后添加日志记录、性能统计等功能。
总的来说,动态代理是实现AOP的一种重要机制,它可以帮助开发人员更加方便地实现对目标对象的增强和控制,从而提高代码可维护性和可扩展性。
//抽象角色:租房
public interface Rent {
public void rent();
}
//真实角色: 房东,房东要出租房子
public class Host implements Rent{
public void rent() {
System.out.println("房屋出租");
}
}
//代理角色:中介
public class Proxy implements Rent {
private Host host;
public Proxy() { }
public Proxy(Host host) {
this.host = host;
}
//租房
public void rent(){
seeHouse();
host.rent();
fare();
}
//看房
public void seeHouse(){
System.out.println("带房客看房");
}
//收中介费
public void fare(){
System.out.println("收中介费");
}
}
//客户类,一般客户都会去找代理!
public class Client {
public static void main(String[] args) {
//房东要租房
Host host = new Host();
//中介帮助房东
Proxy proxy = new Proxy(host);
//你去找中介!
proxy.rent();
}
}
//抽象角色:增删改查业务
public interface UserService {
void add();
void delete();
void update();
void query();
}
//真实对象,完成增删改查操作的人
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("增加了一个用户");
}
public void delete() {
System.out.println("删除了一个用户");
}
public void update() {
System.out.println("更新了一个用户");
}
public void query() {
System.out.println("查询了一个用户");
}
}
//代理角色,在这里面增加日志的实现
public class UserServiceProxy implements UserService {
private UserServiceImpl userService;
public void setUserService(UserServiceImpl userService) {
this.userService = userService;
}
public void add() {
log("add");
userService.add();
}
public void delete() {
log("delete");
userService.delete();
}
public void update() {
log("update");
userService.update();
}
public void query() {
log("query");
userService.query();
}
public void log(String msg){
System.out.println("执行了"+msg+"方法");
}
}
总结:
静态代理和动态代理的代理角色相同,都是为被代理对象提供额外的功能或限制
静态代理的代理类是我们编写的,而动态代理的代理类是在运行时动态生成的
动态代理分为基于接口的动态代理和基于类的动态代理
JDK动态代理是基于接口的动态代理,cglib是基于类的动态代理,javassist也可以用于生成动态代理
在代码中应该体现静态代理和动态代理的异同点,比如注释说明或代码结构等
对于不同的代理方式,应选择最适合的实现方式,例如:如果要代理的对象已实现接口,则可以使用JDK动态代理;如果要代理的对象没有实现接口,则可以使用cglib动态代理
对于JDK动态代理,可以使用InvocationHandler接口和Proxy类来实现,这样可以避免引入第三方库,同时也能够更清楚地表达代理的特性和实现原理
对于cglib动态代理,需要将cglib库添加到项目依赖中,并且被代理对象不能声明成final类型。此外,由于cglib是基于继承实现的,因此需要注意被代理对象中的final方法或private方法在代理类中无法被覆盖的问题。
AOP(面向切面编程)是一种编程思想,旨在将应用程序的不同功能分离出来,从而提高程序的可重用性、灵活性和维护性。它通过在系统中定义横切关注点,将这些关注点与业务逻辑分开处理,从而实现了对系统各个部分的隔离和封装。
AOP 的实现方式主要有两种:静态代理和动态代理。在运行时,AOP 会根据预先设定的切入点,对目标对象进行拦截,并将相关的通知(Advice)插入到目标对象的指定位置,从而影响目标对象的行为。
在 Java 开发中,常见的 AOP 框架有 Spring AOP 和 AspectJ 等。Spring AOP 是基于 Java 动态代理和 CGLIB 动态代理机制实现的,它提供了基于方法拦截和基于注解拦截等多种实现方式,支持前置通知、后置通知、环绕通知、异常通知和最终通知等多种通知类型。AspectJ 则是基于 Java 编译器实现的,具有更强的表达能力和灵活性,可以实现更复杂的 AOP 功能。
总之,AOP 是一种非常有用的编程思想,在实际开发中可以用来实现日志记录、安全检查、性能监控等横切关注点,从而提高应用程序的质量和可维护性。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.10.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
MyBatis
编写pojo实体类
public class User {
private int id; //id
private String name; //姓名
private String pwd; //密码
}
ACID(原子性、一致性、隔离性、持久性)四个特性,这些特性是关系型数据库中事务的重要属性。每个字母代表一个特性:
原子性(Atomicity):指一个事务中所有操作不可分割,要么全部完成,要么全部不完成。
一致性(Consistency):指在事务开始之前和事务结束之后,数据库的完整性约束没有被破坏,即数据必须满足业务规则。
隔离性(Isolation):指多个事务并发执行时,每个事务的执行应该与其他事务隔离开来,互不干扰,防止数据损坏。
持久性(Durability):指当事务提交之后,其所做的修改会永久保存到数据库中,不会因为系统崩溃等异常情况而丢失。
加群联系作者vx:xiaoda0423
仓库地址:https://github.com/webVueBlog/JavaGuideInterview