当前位置: 首页 > news >正文

如何制作自己的网站书签做家务的男人免费观看网站

如何制作自己的网站书签,做家务的男人免费观看网站,营销型网站模版,建站开发Spring IoC IoC:控制反转。将对象创建和对象之间的调用交给Spring容器来管理。好处是降低了对象之间的耦合度。 DI:依赖注入。给bean对象注入依赖的对象。 大白话就是:Spring帮你创建对象,对象的属性如果依赖于某个对象&#xf…

Spring IoC

IoC:控制反转。将对象创建和对象之间的调用交给Spring容器来管理。好处是降低了对象之间的耦合度。

DI:依赖注入。给bean对象注入依赖的对象。

大白话就是:Spring帮你创建对象,对象的属性如果依赖于某个对象,也是Spring为对象注入依赖对象。

怎么理解Spring IoC可以降低对象之间的耦合度?

// 传统高耦合代码
public class UserService {private UserRepository userRepository = new JdbcUserRepository(); // 直接依赖具体类public void saveUser(User user) {userRepository.save(user);}
}

Spring IoC降低对象之间的耦合度:

public class UserService {private UserRepository userRepository; // 依赖接口// 构造器注入public UserService(UserRepository userRepository) {this.userRepository = userRepository;}
}
@Configuration
public class AppConfig {@Beanpublic UserRepository userRepository() {return new JpaUserRepository(); // 只需修改此处即可切换实现}
}

Spring依赖注入的四个方式?

  • 构造函数注入

    • Spring在创建某个类的实例时,会选择这个类的一个构造器创建。
    • 如果只有一个构造器就会默认使用,而如果有多个,则选择标有@Autowired注解的构造器使用。
    • 解析构造函数参数,从容器获取相应的Bean。
    • 创建实例,并完成依赖注入。
  • 字段注入

    • Spring创建完类实例后,扫描 @Autowired 注解的字段,Spring 会从容器中找到匹配的 Bean并注入。
  • setter方法注入

    • Spring创建完类实例后,扫描 @Autowired 注解的方法,从容器中找到匹配的 Bean,并通过反射调用 Setter 方法注入依赖。
  • @Bean 方法参数注入

    • (@Bean )public UserService userService(Environment env),会找到Environment类型的bean注入。

代码解释:

@Component
public class Chef {private Vegetable vegetable; // 依赖抽象(接口)private Egg egg;// 管家(Spring)通过构造函数自动注入食材public Chef(Vegetable vegetable, Egg egg) { this.vegetable = vegetable;this.egg = egg;}public void cook() {Dish dish = new Dish(vegetable, egg);}
}@Component
public class Tomato implements Vegetable { /* ... */ }
@Component
public class Chef {@Autowired  // 字段注入private Vegetable vegetable;  // Spring 会注入 Vegetable 的实例private Egg egg;             // 无 @Autowired,Spring 不会注入(此时 egg = null)// 默认无参构造器(Spring 会调用它)
}
public class Chef {private Vegetable vegetable;private Egg egg;// 必需依赖通过构造函数注入public Chef(Vegetable vegetable) {this.vegetable = vegetable;}// 可选依赖通过 Setter 注入@Autowired(required = false)public void setEgg(Egg egg) {this.egg = egg;}
}
@Bean
public UserService userService(Environment env) {// 从环境变量中读取 "env.mode" 的值String envMode = env.getProperty("env.mode");if ("prod".equals(envMode)) {return new UserServiceImplA(); // 生产环境实现} else {return new UserServiceImplB(); // 默认/开发环境实现}
}

Spring容器启动阶段都会干什么?

  • ApplicationContext applicationContext = new ClassPathXmlApplicationContext(“beans.xml”);

在这里插入图片描述

  • refresh();

在这里插入图片描述

  • obtainFreshBeanFactory()
  • finishBeanFactoryInitialization()

在这里插入图片描述

  • ▲obtainFreshBeanFactory()

这个方法主要干的是:加载和解析配置文件,保存到对应的 Bean 定义中(保存在BeanDefinition中),然后将这些BeanDefinition注册到beanDefinitionMap中。(用于后续bean实例化做准备。)

BeanDefinition 中保存了我们的 Bean 信息,比如这个 Bean 指向的是哪个类、是否是单例的、是否懒加载、这个 Bean 依赖了哪些 Bean 等等。

  • ▲finishBeanFactoryInitialization()

    这个方法主要干的是:对于单实例bean的创建、属性赋值、初始化。

    • preInstantiateSingletons():处理所有非懒加载的单实例

      • List beanNames = new ArrayList(this.beanDefinitionNames); // 获取所有beanName

      • 处理 FactoryBean

      • 处理普通的 Bean:getBean(beanName);// 初始化所有非懒加载的单实例bean

  • ▲getBean(beanName)

    这个方法主要干的是:对于单实例bean的创建、属性赋值、初始化。

    • doGetBean():已经初始化过了就从容器中直接返回,否则就先初始化再返回。
      • createBean() ->Object beanInstance = doCreateBean(beanName, mbdToUse, args) :获得实例化后的bean实例
  • ▲doCreateBean(beanName, mbdToUse, args)

    在这个方法中可以看到bean生命周期的前三个阶段。

    • instanceWrapper = this.createBeanInstance(beanName, mbd, args);:实例化阶段
      • return instantiateUsingFactoryMethod(beanName, mbd, args); // 采用工厂方法实例化
      • return autowireConstructor(beanName, mbd, null, null); // 构造函数依赖注入
      • return instantiateBean(beanName, mbd); //使用无参构造器
    • this.populateBean(beanName, mbd, instanceWrapper);:属性赋值阶段
    • exposedObject = this.initializeBean(beanName, exposedObject, mbd);:初始化阶段

Spring 的 Bean 实例化方式?

方式1:使用构造器实例化

  • 直接通过类的构造器创建 Bean,由 Spring 自动调用。
  • 依赖注入通过构造器参数完成
@Service
public class UserService {private final UserRepository userRepository;// 构造器注入(Spring 自动注入 UserRepository)public UserService(UserRepository userRepository) {this.userRepository = userRepository;}public User getUserById(Long id) {return userRepository.findById(id);}
}@Repository
public class JpaUserRepository implements UserRepository {// 实现数据访问逻辑
}

应用场景:

大多数简单 Bean 的创建,如 Service、Repository 类。

方式2:静态工厂方法

  • 通过类的静态方法返回 Bean 实例,工厂类无需实例化。
  • 方法必须是 static 的。
// 静态工厂类:
public class UserFactory {// 静态方法:直接通过类名调用public static User createUser() {return new User("John");}
}
// 注解配置
@Configuration
public class AppConfig {@Beanpublic static User user() {return UserFactory.createUser(); // 直接调用静态方法,无需实例化 UserFactory}
}

“当 @Configuration 类中的 @Bean 方法是静态的且没有其他需要实例化的成员(如非静态方法或 @Autowired 字段)时,Spring 不会创建该配置类的实例。因为静态方法属于类级别,Spring 可以直接通过类名调用,无需实例化对象。但如果配置类中存在非静态方法或依赖注入字段,Spring 会创建实例以满足这些需求。”

应用场景:

创建全局工具类或整合第三方库的 Bean。

@Bean
public static DataSource dataSource() {return LegacyDataSourceFactory.createDataSource();
}@Bean
public static ExecutorService threadPool() {return Executors.newFixedThreadPool(10);
}

方式3:实例工厂方法

  • 通过一个已存在的工厂 Bean 的非静态方法创建目标 Bean。
  • 方法是非静态的
@Component
public class DataSourceFactory {@Autowiredprivate Environment env;  // 注入环境变量(如 application.properties 中的配置)public DataSource createDataSource() {HikariDataSource dataSource = new HikariDataSource();dataSource.setJdbcUrl(env.getProperty("spring.datasource.url"));dataSource.setUsername(env.getProperty("spring.datasource.username"));dataSource.setPassword(env.getProperty("spring.datasource.password"));return dataSource;}
}@Configuration
public class DataSourceConfig {@Autowiredprivate DataSourceFactory dataSourceFactory;@Beanpublic DataSource dataSource() {return dataSourceFactory.createDataSource();  // 调用实例方法创建 Bean}}

应用场景:工厂类需要依赖其他 Bean 或动态配置

方式4:FactoryBean 接口实例化方式

  • 通过实现 FactoryBean 接口,将复杂对象的创建逻辑封装到 getObject() 方法中。
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory> {private DataSource dataSource;// 依赖注入数据源public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;}@Overridepublic SqlSessionFactory getObject() throws Exception {  // SqlSessionFactory创建过程SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();factoryBean.setDataSource(dataSource);factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mappers/*.xml"));return factoryBean.getObject();}@Overridepublic Class<?> getObjectType() {return SqlSessionFactory.class;}@Overridepublic boolean isSingleton() {return true;}
}// 配置类中注册 FactoryBean
@Configuration
public class MyBatisConfig {@Beanpublic SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();factoryBean.setDataSource(dataSource);return factoryBean;}
}

应用场景:

适合创建bean实例时需要复杂初始化流程,如整合 MyBatis时, 通过 SqlSessionFactoryBean 配置数据源、XML 映射文件路径等,简化 SqlSessionFactory 的创建过程。

bean的生命周期?

实例化、属性赋值、初始化、使用、销毁

  • 实例化:四种实例化方式

  • 属性赋值:

    • 1、收集数据:扫描标有@Autowired的字段或方法。
    • 2、查找依赖:在bean容器中根据类型或名称查找匹配的bean
    • 3、反射注入:通过反射将依赖的bean赋值给字段或者方法。
  • 初始化:

    • 1、BeanPostProcessor.postProcessBeforeInitialization():BeanPostProcessor的前置处理器
    • 2、@PostConstruct注解方法:执行bean类中标有这个注解的方法
    • 3、InitializingBean.afterPropertiesSet():让bean实现InitializingBean接口,重写里头的初始化方法
    • 4、XML/注解中指定的init-method:@Bean(initMethod = “customInit”)
    • 5、BeanPostProcessor.postProcessAfterInitialization():BeanPostProcessor的后置处理器
  • 使用

  • 销毁

说说循环依赖?

对象A 依赖 对象B,对象B 依赖 对象A,就成了循环依赖。

A 实例化的时候,发现依赖 B,创建 B 实例,创建 B 的时候发现需要 A,创建 A1 实例……无限套娃。。。。

Spring 怎么解决循环依赖呢?

Spring能解决循环依赖的条件是:单实例bean,且通过 Setter/字段注入(构造器注入无法解决循环依赖)

Spring 通过三级缓存解决单例 Bean 的循环依赖问题。

  1. 一级缓存存放已完全初始化的 Bean,
  2. 二级缓存存放提前暴露的半成品 Bean(已实例化但未完成属性注入),
  3. 三级缓存存放生成半成品 Bean 的 ObjectFactory

以 A 依赖 B,B 依赖 A 为例:

  • 创建 A 时,实例化后将其 ObjectFactory 放入三级缓存。
  • 填充 A 的属性时发现依赖 B,触发 B 的创建。
  • 创建 B 时同样将 ObjectFactory 放入三级缓存,填充 B 的属性时发现依赖 A,它就从缓存里找 A 对象。依次从⼀级到三级缓存查询 A。
  • B从三级缓存中通过对象⼯⼚生成A的早期引用,将 A 的早期引用放⼊⼆级缓存,并从三级缓存移除。此时,B 已经实例化并且初始化完成了,把 B 放入⼀级缓存。
  • A 继续完成属性注入和初始化。顺利从⼀级缓存拿到实例化且初始化完成的 B 对象,A 对象创建也完成,删除⼆级缓存中的 A,同时把 A 放⼊⼀级缓存。
  • 最后,⼀级缓存中保存着实例化、初始化都完成的 A、B 对象。

ObjectFactory

以 A 依赖 B,B 依赖 A 为例:

  • 创建 A 时,实例化后将其 ObjectFactory 放入三级缓存。
  • 填充 A 的属性时发现依赖 B,触发 B 的创建。
  • 创建 B 时同样将 ObjectFactory 放入三级缓存,填充 B 的属性时发现依赖 A,它就从缓存里找 A 对象。依次从⼀级到三级缓存查询 A。
  • B从三级缓存中通过对象⼯⼚生成A的早期引用,将 A 的早期引用放⼊⼆级缓存,并从三级缓存移除。此时,B 已经实例化并且初始化完成了,把 B 放入⼀级缓存。
  • A 继续完成属性注入和初始化。顺利从⼀级缓存拿到实例化且初始化完成的 B 对象,A 对象创建也完成,删除⼆级缓存中的 A,同时把 A 放⼊⼀级缓存。
  • 最后,⼀级缓存中保存着实例化、初始化都完成的 A、B 对象。
http://www.dtcms.com/a/436496.html

相关文章:

  • 如何制作网站图片线上销售模式有哪些
  • 洛谷题解P1518 [USACO2.4] 两只塔姆沃斯牛 The Tamworth Two
  • 网站建设辅助导航平面设计公司简介怎么写
  • 杭州搭建网站小程序开发兼职要多少钱
  • php技术应用于中小企业网站开发郑州企业网站优化服务哪家好
  • 大连企业做网站公司排名python 网站开发小项目
  • 企业 门户型网站区别枣庄手机网站制作
  • 学校网站建设目的及功能定位免费图片制作app软件哪个好
  • 关于电商网站规划方案Dw怎么做网站往里面加标题和字
  • 英语学习-Saints040-1
  • 湖南营销类网站设计甘肃建设厅网站执业注册中心
  • 怡清源在慧聪网网站建设情况专业开发app公司
  • 什么是网站功能需求网站建设顶部图片
  • 凡科建站代理企业手机网站源码下载
  • 合肥做机床的公司网站用金山文档编辑信息泄露隐私
  • 网站要怎么盈利上海营销网站
  • 谁给个网站啊急急急2021ppt模板免费模板下载
  • 常州网站设计食品网站建设 网站定制开发
  • 蚌埠网站建设专业的公司慢查询 wordpress
  • 网站优化外包自己做的网站发布到网上视频播放不了
  • 自己建设网站怎么被百度收入制作二维码
  • 网站做百度推广要多少钱个人备案网站做淘宝客可以
  • 建设银行深圳培训中心网站用html框架做网站
  • 石家庄做网站公司有哪些有创意的域名
  • 河北综合网站建设系列平面设计类网站有哪些
  • 深圳品牌做网站公司网站分别
  • c 做网站实例搜索网址网站建站
  • 苍南哪里有网站建设公司自动点击竞价广告软件
  • 自建站英文wordpress小工具九宫格
  • 老会计手把手教做帐官方网站深圳建设怎么样