spring笔记

Spring全家桶(官网地址

Spring Framework

Spring Boot

Spring Cloud

Spring Cloud Data Flow

1.0 Spring Framework

Spring Core

        - IOC、AOP

Spring Data Access

        - Transactions、Spring MyBatis、Mybatis-Plus

Web Servlet

        - Spring MVC

Integration

        - Email、Scheduling、AMQP、Security

1.1 Spring IoC

        - Inversion of Control 控制反转,是一种面向对象编程的设计思想

        - Dependency Injection 依赖注入,是IoC思想的实现方式

        - IoC Container IoC容器,是实现依赖注入的关键,本质上是一个工厂

约定大于配置:

        通过配置文件将bean注入容器管理

       

1.2 简单分析Spring Boot启动类

注解:@SpringBootApplication:

自定义注解所需要的:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited

下面是SpingBoot核心注解:
配置注解:
@SpringBootConfiguration:
     点进去查看:本质上就是一个元注解: @Configuration也是一个元注解,(annotation = Component.class)注入(在运行时能使用这个注解)。

组件扫描注解:
@ComponentScan:会自动扫描包下的bean装配到容器,它会扫描配置类所在的包和子包的bean(需要有@Controller、@Service、@Repository、它们都是由@Component实现的)加入注解就会被Spring容器管理。

核心注解:
@EnableAutoConfiguration:启动自动配置(Spring最核心的注解 )

2.1 Spring 容器管理

通过spring容器获取到bean:

package top.chenxiky.community;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import top.chenxiky.community.dao.AlphaDao;
import top.chenxiky.community.dao.AlphaDaoHibernateImpl;


/**
 * 测试类
 *
 * @author chenxiky
 * @version 1.0.0
 * @since 2022/10/02/10:37
 */
@SpringBootTest
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = CommunityApp.class) // 配置类
public class CommunityAppTest implements ApplicationContextAware { // 获得容器需实现

    // 存储spring容器
    private ApplicationContext applicationContext;

    /**
     * 加载配置类
     * ApplicationContext spring容器 是它的子接口(子类扩展更多 通常用子类去)
     *      HierarchicalBeanFactory 是它的子接口
     *      BeanFactory就是spring的顶层接口
     *      spring会扫描到ApplicationContextAware它会调用set方法
     *
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Test
    public void testApplicationContext() {
        // 获取到容器的地址
        System.out.println(applicationContext);
        // 通过从ApplicationContext这个容器里 获取到自动装配的bean
        // 这里可以通过获取父类的方法 也可以精准的获取实现的bean(AlphaDaoHibernateImpl.class)
        // 方式一
        AlphaDao alphaDao = applicationContext.getBean(AlphaDao.class);
        System.out.println("通过父类(接口):"+alphaDao.select());
        // 方式二(成功获取到bean)
        AlphaDao alphaDao1 = applicationContext.getBean(AlphaDaoHibernateImpl.class);
        System.out.println("通过子类:"+alphaDao1.select());
    }
}

 两个类同时实现了AlphaDao接口的select方法:

 此时执行原来的测试代码就会报错:

异常信息:No qualifying bean of type 'top.chenxiky.community.dao.AlphaDao' available: expected single matching bean but found 2: alphaDaoHibernateImpl,alphaDaoMyBatisImpl

 解决方案

1.方式一(只获取一个bean):

        想运行的bean上加上:@Primary注解,就会优先执行这个bean(只会执行一个)

我们依赖的接口不是它实现的本身,我们需要更改的实现类的时候只需要新建一个实现类,并加上这个注解就可以了。

2.方式二(通过bean名字获取所有bean):

        bean的名字是类名首字母小写,类名如果比较长也可以改一下bean的名字 自定义bean的名字@Service("写bean的名字"),可以通过bean的名称获取bean.

 具体代码:

    @Test
    public void testApplicationContext2() {
        // 获取到容器的地址
        System.out.println(applicationContext);
        // 通过从ApplicationContext这个容器里 获取到自动装配的bean(通过注解优先拿到:@Primary)
        AlphaDao alphaDao = applicationContext.getBean(AlphaDao.class);
        System.out.println(alphaDao.select());

        AlphaDao alphaDao2 = applicationContext.getBean("alphaDaoHibernateImpl",AlphaDao.class);
        System.out.println(alphaDao2.select());
    }

演示bean的创建 初始化 销毁:

package top.chenxiky.community.sevice;

import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * 业务测试类
 *
 * @author chenxiky
 * @version 1.0.0
 * @since 2022/10/02/11:45
 */
@Service
public class AlphaService {

    // 证明@PostConstruct是在构造器之后调用
    public AlphaService() {
        System.out.println("实例化AlphaService...");
    }
    // 初始化方法
    // 容器管理整个bean 创建 初始化 销毁
    @PostConstruct  // 这个方法会在构造器之后调用 初始化方法通常是在构造器之后调用
    public void init() {
        System.out.println("初始化AlphaService...");
    }

    // 销毁方法
    @PreDestroy  // 在销毁对象之前调用这个方法
    public void Destroy() {
        System.out.println("销毁AlphaService...");
    }

}

测试类:


    @Test
    public void testBeanManagement() {
        AlphaService alphaService = applicationContext.getBean(AlphaService.class);
        System.out.println(alphaService);
    }

可以清楚的看到bean初始化的过程: 对象是在构造器实例化、再初始化bean 、bean的实例(AlphService@38499e48)、在程序结束的时候 ,最后销毁bean.

 spring默认是单例

@Scope("singleton")  // 单例 

@Scope("prototype") // 多例

 采用多例的情况

 小结:上面是通过spring去管理自己的bean

2.2 管理第三方的bean

package top.chenxiky.community.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.text.SimpleDateFormat;

/**
 * 管理第三方配置类(例如redis 连接池等操作)
 *
 * @author chenxiky
 * @version 1.0.0
 * @since 2022/10/02/12:39
 */

@Configuration // 标明是一个配置类 交由spring管理
public class AlphaConfig {

    /**
     * <p>时间格式化配置类</p>
     * <p>方法名就是bean的名字 如果不自定义的话</p>
     */
    @Bean
    public SimpleDateFormat simpleDateFormat() {
        // 实例化这个bean
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    }
}

测试类:

    /**
     * 配置类的bean
     */
    @Test
    public void testBeanConfig() {
        SimpleDateFormat simpleDateFormat = applicationContext.getBean(SimpleDateFormat.class);
        // 格式化当前日期
        System.out.println("格式化当前日期:" + simpleDateFormat.format(new Date()));
    }

 注意:上面的方式都是通过主动去获取 ,方式不灵活

2.2.1 通过字段注入的方式

通过构造器 、set方法、字段注入bean

@Autowired(按类型注入 byType)

        如果需要字段名称注入可结合:@Qualifier注解按照Autowared注入spring会警告,因为它是基于Spring的,不推荐以这种方式注入bean。

        缺点:严重依赖Spring,耦合度太高

例子:

    @Autowired

     private AlphaConfig alphaConfig;

     // 注意这里会把这个类型的bean都注入 只想注入某个bean要用@Qualifier结合

  @Autowired
  @Qualifier("alphaDaoHibernateImpl")
  private AlphaDao alphaDao;

@Resource(按名称注入 byName)

        它是java的jar包下的注解,在任何框架下都可以使用,推荐使用这种方式注入bean,它是按照bean名称注入的。

        优点:耦合度低。

3.AOP详解

        AOP切面编程,不侵入代码,它主要通过动态代理的方式实现的织入。动态代理主要有:JDK动态代理、CGLIB。

      默认使用JDK动态代理,利用接口实现代理;只能作用在接口上;

      CGLIB 动态代理,利用继承的方式实现代理;可作用在类上也可在接口上;

        未完待完善... 

4. 自动装配的原理(@EnableAutoConfiguration)详解

        未完待续....敬请期待!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值