Spring学习记录2

1.注解开发的好处

无需编写xml文件,通过注解全部配置,可以简化工程,但是存在对第三方资源配置时比较复杂的问题(如数据库连接池)。

public class JDBCConfig {

    //静态 非静态没有任何影响
    @Bean("dataSource")
    public DruidDataSource getDataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("");
        ds.setUrl("");
        ds.setUsername("");
        ds.setPassword("");
        return ds;
    }

}

因为我们没法深入Druid的代码,去使用properties的方式给这四个字断进行赋值。

2.Spring常用注解

1.对于注解的使用,我们需要进行开启,也就是让Spring扫描我们加了注解的类,让它帮我们造那些类的实例,所以要制定Spring扫描哪些类,也就是指定Spring扫描的包:

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

但在这里还是用到配置文件了,我们也可以完全不用到配置文件,使用配置类+纯注解的方式消除配置文件,通过@Configuration来指定配置文件所在的类,@ComponentScan来指定扫描的包。

@Configuration
@ComponentScan("com.example")
public class SpringConfig {
}

此时若要加载这个配置类,也不能再使用ClassPathXmlApplicationContext,而需要用AnnotationConfigApplicationContext来进行加载,加载内容填配置类的字节码即可。

ApplicationContext ac = 
new AnnotationConfigApplicationContext(SpringConfig.class);

若出现多个配置类,可以让一个配置类为主类,其它配置类通过@Import的方式引入,@Import仅可写一次,若有多个以数组方式给出({a1.class,a2.class....}),如JDBC数据库池配置引入:

public class JDBCConfig {

    //静态 非静态没有任何影响
    @Bean("dataSource")
    public DruidDataSource getDataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("");
        ds.setUrl("");
        ds.setUsername("");
        ds.setPassword("");
        return ds;
    }

}

@Configuration
@ComponentScan("com.example")
@Import(JDBCConfig.class)
public class SpringConfig {
}

当然,也可以没有主从关系的引入,都通过类来加载,加载顺序按填入参数顺序:

ApplicationContext ac = 
new AnnotationConfigApplicationContext(SpringConfig.class, JDBCConfig.class);

所以对于第三方配置的bean,无需使用@Component的方式进行依赖注入,直接以配置的方式被导入即可。

2.声明一个类为bean,让其能够被Spring的IoC容器管理,通过注解:@Component,@Controller,@Service,@Repository其中之一即可,不同的名字仅代表不同含义,功能相同,只要将其定义在类上方即可,同时我们还可以给其起id,根据需求,不一定要有:

@Component("userService")
@Scope("singleton")
public class UserServiceImpl implements UserService

bean的作用域通过@Scope注解声明,属性为单例与非单例,默认单例。

3.bean的声明周期随作用域不同而不同,对于初始化方法与销毁方法的注解声明使用@PostConstruct与@PreDestory(仅在上下文关闭时生效):

@PostConstruct
public void init(){
    System.out.println("init");
}

@PreDestroy
public void destory(){
    System.out.println("destory");
}

4.使用bean加载第三方资源,此时@Bean作为一个方法注解加在获取第三方资源的方法上,可以起个id,该方法的返回值作为spring管理的bean

public class JDBCConfig {

    //静态 非静态没有任何影响
    @Bean("dataSource")
    public DruidDataSource getDataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("");
        ds.setUrl("");
        ds.setUsername("");
        ds.setPassword("");
        return ds;
    }

}

5.bean的非引用与引用类型注入

此时由于注解可以加到当前类中,所以不再受私有变量的影响,不需要set方法了。

对非引用类型使用@Value注解:

@Value("3")
private int number;

对于引用类型使用@Autowired与@Qualifier,对于@Qualifier如果不存在同类型冲突的问题不需要使用,@Qualifier主要根据id去唯一匹配类型。

//required代表是否允许为空,默认为false
@Autowired(required = false)
//@Qualifier("userDao")
private UserDao userDao;

@Autowired的匹配方式为默认按照类型装配,所以不需要给被装配类型起别名,正常情况也不需要使用@Qualifier指定,但是若存在类型相同的问题,此时会根据变量名(变量名与@Component时声明的id)进行匹配。

若不给id,并且出现多类型相同的问题,那么此时可以用@Primary指明,首要配对哪个。

//先配对
@Primary
@PropertySource("classpath:jdbc.properties")
public class UserDaoImpl implements UserDao

@Component
@PropertySource("classpath:jdbc.properties")
public class UserDaoImpl2 implements UserDao 

6.Properties文件加载

在需要使用的类上方使用@PropertySource加载,且加载一次,全局通用,并且不能用通配符的形式。加载完成后,使用注入的方式注入即可。

@Component
@Primary
//还可以指定找不到怎么样
@PropertySource(value = "classpath:jdbc.properties",ignoreResourceNotFound = false)
public class UserDaoImpl implements UserDao {

    @Value("${jdbc.userName}")
    private String userName;

    @Value("${jdbc.password}")
    private String password;

    @Override
    public void save() {
        System.out.println("dao saving"+userName+password);
    }

}

3.bean的加载控制

加载控制的目的是控制类的加载顺序。

我们可以通过@DependsOn的方式来实现加载顺序控制,它是使被注解的类OR方法在指定bean加载完毕后加载。@Order是加在类上的注解,它通过数值的大小来控制类的加载顺序。@Lazy是加在类或者方法上的注解,控制加载时机,延迟加载。

@DependsOn的一个应用场景,比如有个消息发布与订阅的服务,此时应该先开启订阅,再开启发布,这样才能不丢失数据。

@Lazy的一个应用场景,程序出现灾难后对应的应急预案处理是启动容器时的加载时机。

@Order,可以指定先加载系统级配置。

4.案例2

将案例1中的xml配置文件方式修改为注解方式。

public class JDBCConfig {

    @Value("${jdbc.driver}")
    private String JDBCDriver;

    @Value("${jdbc.url}")
    private String Url;

    @Value("${jdbc.username}")
    private String Username;

    @Value("${jdbc.password}")
    private String Password;

    @Bean
    public DruidDataSource getDruidDataSource(){
        DruidDataSource dds = new DruidDataSource();
        dds.setDriverClassName(JDBCDriver);
        dds.setUrl(Url);
        dds.setUsername(Username);
        dds.setPassword(Password);
        return dds;
    }

}

public class MybatisConfig {
    
    //这里很重要
    //注意dataSource要写在参数里,由Spring装配
    @Bean
    public SqlSessionFactoryBean getSqlSessionFactoryBean(@Autowired DataSource dataSource){
        SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
        ssfb.setDataSource(dataSource);
        return ssfb;
    }

    @Bean
    public MapperScannerConfigurer getMapperScannerConfigurer(){
        MapperScannerConfigurer mscf = new MapperScannerConfigurer();
        mscf.setBasePackage("com.example.dao");
        return mscf;
    }

}

@Configuration
@ComponentScan("com.example")
@PropertySource("classpath:jdbc.properties")
@Import({JDBCConfig.class,MybatisConfig.class})
public class SpringConfig {
}

也就是把之前在applicationContext.xml中的配置放入了java代码中。

5.IoC底层核心原理

核心架构:BeanFactory,AutowireCapableBeanFactory,ListableBeanFactory。

1.组件扫描器,我们可以根据需求来加载有必要的bean,排除指定bean。

我们可以通过配置文件的方式也可以通过注解的方式。

配置文件的方式:

<bean id="filter" class="com.example.config.filter.MyTypeFilter"/>
    
<context:component-scan base-package="com.example" >
    <context:exclude-filter type="custom" expression="filter"/>
<!--        <context:include-filter type="" expression=""/>-->
</context:component-scan>>

注解的方式:

@ComponentScan(value = "com.example",
        excludeFilters = {@ComponentScan.Filter(
                type = FilterType.CUSTOM,
                classes = MyTypeFilter.class)})

type指代过滤器的类型,然后根据指定的类型,指定指定的过滤:

public enum FilterType {
    ANNOTATION,
    ASSIGNABLE_TYPE,
    ASPECTJ,
    REGEX,
    CUSTOM;

    private FilterType() {
    }
}

若选择自定义过滤器,则可以选择CUSTOM,自定义过滤器需要继承TypeFilter这个注解:

public class MyTypeFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        String className = classMetadata.getClassName();
        if("com.example.service.impl.AccountServiceImpl".equals(className)){
            return true;
        }
        return false;
    }
}

通过元数据可以获得注解的bean的名称,若match返回为true则被过滤,反之则不。

2.导入器,在需要配置大量bean的时候,可以通过导入器指定要导入的bean,从而不用对bean加@Component注解或xml配置。自定义导入器需要继承自ImportSelector,最后通过在SpringConfig中使用@Import导入配置。

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        ResourceBundle rb = ResourceBundle.getBundle("import");
        String className = rb.getString("className");
        return new String[]{className};//这个返回的字符串数组就是要导入bean的全类名
    }
}

并且为了解耦合,我们可以将bean全类名的获取改到从配置文件获取。

3.注册器,之前我们对于bean的注册,要么是通过在xml文件中配置扫描,要么在配置类中使用注解配置扫描,我们也可以自定义注册器来实现,在定义完注册器后,可以将其在配置类中通过@Import引入,自定义注册器需要实现ImportBeanDefinitionRegistrar。

public class MyImportBeanDefinitionResgistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(beanDefinitionRegistry,false);
        scanner.addIncludeFilter(new MyTypeFilter());
        scanner.scan("com.example");
    }
}

在这其中也可以指定过滤器,因为原本若通过注解指定过滤器就是在扫描注解中。

4.bean初始化过程解析:

Spring通过工厂方法+文件的方式实现解耦合,所以在正式创建bean之前会创建工厂类,通过工厂创建bean。

我们可以通过自定义BeanFactoryPostProcessor类的子类对象来解决bean工厂创建后,子类创建前的处理,仅执行一次,实现好通过import引入。

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("处理....");
    }
}

我们可以通过BeanPostProcessor来解决所有bean初始化之前的统一动作,用于对bean创建前业务的处理,每个bean创建都会处理,但记住系统的bean是在一开始全部初始化的,实现好也通过import引入。

public interface BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

我们可以通过InitializingBean来解决每个bean创建前个性化的动作,不是每个bean都统一处理,每个bean自己实现InitializingBean接口。

@Service
public class AccountServiceImpl implements AccountService, InitializingBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("account的个性化");
    }
}

5.繁杂bean的初始化是通过FactoryBean来解决,达到简化操作的目的,比如SqlSessionFactoryBean,而BeanFactory是Spring Bean容器的顶层接口,定义了Bean的相关操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 很高兴听到您对Spring Boot 2的学习感兴趣。Spring Boot是一个基于Spring框架的快速开发应用程序的工具,它提供了一种简单的方式来创建和配置Spring应用程序。以下是一些学习Spring Boot 2的笔记: 1. Spring Boot 2的新特性:Spring Boot 2相对于Spring Boot 1.x版本来说,有许多新的特性和改进。例如,它支持Java 9和10,提供了更好的响应式编程支持,以及更好的安全性和监控功能。 2. Spring Boot 2的核心组件:Spring Boot 2的核心组件包括Spring Framework、Spring MVC、Spring Data和Spring Security等。这些组件提供了一系列的功能和工具,使得开发人员可以更加轻松地构建和管理应用程序。 3. Spring Boot 2的配置:Spring Boot 2的配置非常简单,它提供了一种基于注解的方式来配置应用程序。开发人员可以使用@Configuration和@Bean注解来定义配置类和Bean。 4. Spring Boot 2的启动器:Spring Boot 2提供了一系列的启动器,这些启动器可以帮助开发人员快速地集成各种常用的框架和库,例如Spring Data JPA、Spring Security、Thymeleaf等。 5. Spring Boot 2的测试:Spring Boot 2提供了一系列的测试工具,例如Spring Boot Test、Mockito、JUnit等。这些工具可以帮助开发人员编写高质量的单元测试和集成测试。 希望这些笔记对您学习Spring Boot 2有所帮助。如果您有任何问题或疑问,请随时联系我。 ### 回答2: Spring Boot 是一个非常流行的开源框架,它的目的是使 Spring 应用程序的开发过程更加简单、快速和高效。Spring Boot 2 是 Spring Boot 框架的第二个版本,已经成为了当今业界最流行的 Java 开发框架之一。 Spring Boot 2 的新特性: 1. 支持 JDK 9。Spring Boot 2 已经支持 JDK 9 所带来的新特性和功能。 2. 基于 Reactive Streams 的编程模型。Spring Boot 2 增加了对 Reactive Streams 的支持,可以开发响应式应用程序,从而提高了系统的吞吐量和性能。 3. 异步服务器支持。Spring Boot 2 已经支持多种异步服务器,包括 Netty、Undertow 和 Tomcat。 4. 更全面的 Actuator 组件。Actuator 是 Spring Boot 的监控和管理组件,Spring Boot 2 在 Actuator 组件上增加了更多的指标、健康检查和应用程序信息。 5. 更好的自定义配置。Spring Boot 2 简化了自定义配置的流程,使得用户可以更快速地配置应用程序。 学习 Spring Boot 2 的步骤如下: 1. 掌握 Spring 基础知识。学习 Spring Boot 2 前需要掌握 Spring MVC、Spring Data 等相关的知识。 2. 下载安装 Spring Boot。Spring Boot 2 可以在官网上下载。 3. 学习 Spring Boot 核心组件。包括 Spring IoC、Spring AOP、Spring MVC 等核心组件。 4. 开发一个 Spring Boot 应用程序。可以从一个简单的 Hello World 开始,逐渐增加功能,学习和理解 Spring Boot 的各种特性和功能。 5. 掌握 Spring Boot 的自动配置。Spring Boot 的自动配置可以大大减少开发人员的工作量,学习和掌握自动配置非常重要。 总之,学习 Spring Boot 2 需要不断地实践和探索,只有通过实际的开发经验才能真正掌握和学会这个框架。 ### 回答3: Spring Boot是一款基于Spring框架的快速应用开发框架。在应用开发的过程中,Spring Boot可以自动配置一个相对完整的Spring应用程序,从而大大减少了开发者的工作量,提高了开发效率。显然,它的学习是很有必要的。 Spring Boot 2.x版本相比于1.x版本在很多方面都进行了升级和改进。在学习的过程中,需要关注的重点在以下几点: 1. 新建Spring Boot项目 Spring Boot提供了Spring Initializr来快速创建新的Spring Boot项目。在构建项目的过程中,我们可以自定义项目的基本信息、项目类型、依赖关系等,可以根据需求灵活选择。 2. Spring Boot自动配置 Spring Boot借助于自动配置功能,可以为开发者免去大量的配置工作。Spring Boot把一些常用的配置提取为Starter,开发者只需要引入这些Starter即可实现自动配置,大大降低了开发成本。 3. Spring Boot集成 Spring Boot集成了众多流行的框架,如MyBatis、Hibernate、JPA、Thymeleaf等,只需要简单的配置就可以实现对这些框架的集成,使得在开发中更加方便。 4. Spring Boot监控管理 Spring Boot通过Actuator提供了一系列配置和管理服务,可以实现对Spring Boot应用程序的监控和管理。开发者可以通过这些服务来监控应用程序的运行状态、访问量、资源使用情况等。 5. Spring Boot测试 Spring Boot天生适合进行单元测试和集成测试,可以使用JUnit、Mockito、Spring Test等框架进行测试。同样可以利用Spring Boot提供的Test Starter进行自动配置,减少测试的开发成本。 以上就是Spring Boot 2的一些学习笔记,它的结构简洁,代码清晰,便于开发者使用。无疑,Spring Boot 2是一个非常适合作为开发者日常工作的框架。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值