Spring IOC AOP以及Bean的底层解析理解

Spring IOC AOP以及Bean的底层解析理解

IOC的底层原理、创建对象与注入方式

IOC容器

  • IOC即是控制反转,把对象创建的过程与对象的调用过程交给Spring容器来进行管理
  • 使用了工厂模式,耦合度比较低

IOC底层原理

IOC的三个主要组成部分:XML解析、工厂模式、反射

先从最原始的编程方式来介绍:

awd

一个类去实例化另外一个类,要是碰到实例多个类,耦合度比较高。这个时候!!可以用一下工厂模式来减低耦合度

adwd

通过中间的一个工厂类,我们在多个类调用时,只需要实例一个工厂类就可以,减低了代码间的耦合度。!!但是,我们可以通过IOC容器,通过xml配置文件和反射+工厂模式 来处理

w

以这种形式将耦合度降低到最低限度,这也是IOC的底层原理XML配置!!Java反射!工厂模式


IOC(BeanFactory)

  • IOC思想基于IOC容器,IOC容器就是上面的对象工厂
  • IOC容器的俩种实现方式(俩个接口)
    • BeanFactory:IOC容器的基本实现,是Spring使用的内部接口,不建议开发人员使用,在读取配置文件时,加载配置文件并没有创建对象,而是等获取对象的时候再去创建
    • ApplicatonContext:BeanFactory的子接口,有着更强大更完善的功能,供开发人员使用与BeanFactory不同,加载配置文件就将所有的对象创建完毕

在实际开发中我们应该选择ApplicationContext,将所有的对象在服务器启动时创建完成,可以减少运行时间


DI的注入方式

先定义一个User类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class User {

private String name;
private String sex;

User(String name,String sex){
this.name=name;
this.sex=sex;
}

public void setSex(String sex) {
this.sex = sex;
}
public void setName(String name) {
this.name = name;
}

}

①使用set方法,设值注入

1
2
3
4
5
6
7
8
<!-- 配置User对象创建 -->
<bean id="user" class="com.yellowstar.pojo.User" >
<!-- 通过set方法注入属性 -->
<!-- name为对应的属性命,value为对应的属性值 -->
<property name="name" value="Jerry"></property>
<property name="sex" value="boy"></property>
</bean>

注意,实体类中必须有set方法才可以使用这种注入

②构造注入

1
2
3
4
5
6
7
<!-- 配置Book对象创建 -->
<bean id="book" class="com.yellowstar.pojo.Book">
<!-- 通过构造方法注入属性 -->
<constructor-arg name="bname" value="钢铁是怎样炼成的"></constructor-arg>
<constructor-arg name="bauthor" value="尼古拉·奥斯特洛夫斯基"></constructor-arg>
</bean>

③注解注入

先在XML配置中导入

1
2
<context:annotation-config></context:annotation-config>
<context:component-scan base-package="*"></context:component-scan>

注解的属性有:

  • @Component

  • @Service

  • @Controller

  • @Repository

以上是属于放在方法头部的注解

根据属性注入

  • @Autowired:根据属性类型进行自动装配
  • @Qualifier:根据名称进行注入,要和@Autowired 一起使用。会出现一个接口有多个实现类或一个类有多个子类,此时就需要使用@Qualifier指明注入的是哪一个
  • @Resource:可以根据类型注入也可根据名称注入。当不指定name时根据类型注入,指定name时根据名称注入。
  • @Value:注入普通类型属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Service
public class UserService {
@Autowired
private UserDao userDao;

@Autowired
@Qualifier(value = "userDaoImpl")
private UserDao userDao;

@Resource(name = "userDaoImpl")
private UserDao userDao;

@Value(value = "helloword")
private String name;


}

Bean的作用域

bean的作用域强行背了那么久,总算看到了人话说的理解方式了

bean的作用域是指在spring中设置Bean实例是单实例还是多实例,默认是单实例

简而言之:用单例的话,对象都是同一个地址,用了prototype去实例化,就是分配不同地址

①singleton(单例)–默认

1
<bean id="myBean" class="com.yellowstar.pojo.MyBean" scope="singleton"></bean>

②prototype(原型–多实例)

1
<bean id="myBean" class="com.yellowstar.pojo.MyBean" scope="prototype"></bean>

测试一下

1
2
3
4
5
6
7
8
9
10
11
@Test
public void test5(){
ApplicationContext context = new ClassPathXmlApplicationContext("Bean4.xml");
//先去获取对象
User user1 = context.getBean("myBean", User.class);
User user2 = context.getBean("myBean", User.class);
//如果作用域是singleton,结果是true
//如果作用域是prototype,结果是false
System.out.println(user1 == user2);
}


以下③~⑤使用在Java Web

③session

④request

⑤globalSession

163758-20181112115102629-2030460029.png

Bean的生命周期(最复杂)

我自己总结的大致流程

-2022-09-21-173853.jpg

这里难以解释清楚,我推荐去查看这篇博文,讲解清楚得我怀疑人生

点击这里,学习下Bean的生命周期


文章结合本人理解以及CSDN博文,点击查看->,梳理了下大致的理解

Spring AOP

什么是AOP

​ aop 即面向切面编程,在不改源码的情况下,通过切面对业务逻辑进行增强,降低代码的耦合性

AOP的底层是如何实现的

①有接口的情况,JDK动态代理

创建接口实现类的代理对象,增强类的方法

a

②没有接口的情况,使用CGlib动态代理

创建子类的代理对象,增强类中的方法

Spring的事务管理的实现机制

事务管理是什么

事务这个概念是数据库层面的,Spring只是基于数据库中的事务进行了扩展,以及提供了一些让程序员能够更加方便操作的方式

事务管理分为:

  • 编程式事务管理
  • 声明式事务管理(常用)

​ ①使用Spring AOP XML 方式 (<基于 tx / AOP 配置的声明式事务管理方式) 进行配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 <!-- 5.配置transactionManager事务管理器:依赖于dataSource数据源 --> 
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 6.结合AOP实现事务的织入:配置事务的通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 给方法配置事务,配置事务的传播特性:propagation -->
<tx:attributes>
<!-- #1 分别给插入、删除和修改用户的方法,配置propagation事务属性,其值为REQUIRED -->
<tx:method name="insert" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<!--#2 给查询用户方法设置只读-->
<tx:method name="select" read-only="true"/>
<!-- #3 给所有方法(*指所有方法)配置propagation事务属性,值也设为REQUIRED -->
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>

​ ②使用Spring AOP Annotation 方式 (即使用@Transactional注解实现声明式事务管理)

1
2
3
4
5
6
7
<!-- 5.配置transactionManager事务管理器:依赖于dataSource数据源 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>

<!-- 6.注册事务管理驱动 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

Java实现:

1
2
3
4
5
6
7
8
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,readOnly = true)
// 重写getUsers方法
public List<User> getUsers() {
// 获取UserMapper对象
UserMapper userMapper = sqlSessionTemplate.getMapper(UserMapper.class);
// 返回UserMapper对象的getUsers方法
return userMapper.getUsers();
}

事务的传播级别

七种事务传播行为,默认为REQUIRED

  • REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务,则是常见的选择
  • SUPPORTS:支持当前事务,如果当前没有事务,就以非实物方式执行
  • MANDATORY:支持当前事务,如果当前没有事务,就抛出异常
  • REQUIRED_NEW:新建事务,如果当前存在事务,把当前事务挂起
  • NO_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
  • NEVER:以非事务方式执行,如果当前存在事务,则抛出异常
  • NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务