欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring工作常用方法

程序员文章站 2022-03-26 17:18:06
文章目录前言一、XML配置和配置类形式1.1 XML配置形式1.2 配置类配置1.2.1 普通配置1.2.2 包扫描二、使用步骤1.引入库2.读入数据总结1.XML配置 和 配置类的形式1.1 XML配置形式如下前言主要记录下,在工作中Spring常用的一些注解方法工程架构如下pom文件如下


前言

主要记录下,在工作中Spring常用的一些注解方法

工程架构如下
Spring工作常用方法

pom文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.cch</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.4.RELEASE</spring-boot.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.4.RELEASE</version>
                <configuration>
                    <mainClass>com.cch.demo.DemoApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

一、XML配置和配置类形式

1.1 XML配置形式

现在非主流了
在resource目录下创建app.xml
配置如下

<?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="person" class="com.cch.demo.domain.Person"></bean>
</beans>

在测试DemoApplicationTests类进行测试

@SpringBootTest(classes = DemoApplication.class)
public class DemoApplicationTests {

    @Test
    public void classPathXmlTest(){
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("app.xml");
        Person person = (Person) ctx.getBean("person");

        System.out.println(person);
    }

}

结果如下
获取到bean对象
Spring工作常用方法

1.2 配置类配置

1.2.1 普通配置

主流 的方式
在config 包下创建AppConfig
代码如下

/**
 * @Configuration 表明这是一个配置类,之前是通过xml读取的配置,现在通过这里读取
 * @Author chenchanghui
 * @date 2020/11/26 15:43
 */
@Configuration
public class AppConfig {
    /**
     *  @Bean  这个注解表明产生一个bean对象,像xml文件里面的<bean><bean/>标签
     * @return 
     */
    @Bean
    public Person person(){
        return new Person();
    }
}

在测试DemoApplicationTests类进行测试

    /**
     * AnnotationConfigApplicationContext  和 ClassPathXmlApplicationContext都是spring的容器
     * AnnotationConfigApplicationContext 通过注解配置类的 spring 上下文
     * ClassPathXmlApplicationContext  通过xml文件获取spring的上下文
     */
    @Test
    public void annotationConfigTest() {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        Person person = (Person) ctx.getBean("person");
        System.out.println(person);
    }

结果如下
Spring工作常用方法

1.2.2 包扫描

概念总览
@ComponentScan.Filter type的类型

a)注解形式的FilterType.ANNOTATION @Controller @Service @Repository @Compent 
b)指定类型的 FilterType.ASSIGNABLE_TYPE @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value ={TulingService.class}) 
c)aspectj类型的 FilterType.ASPECTJ(不常用) 
d)正则表达式的 FilterType.REGEX(不常用)
e)自定义的 FilterType.CUSTOM

AppConfig配置如下

//@ComponentScan(basePackages = {"com.cch.demo.dao"})  表示扫描dao的组件
@ComponentScan(basePackages = {"com.cch.demo.dao"})
@Configuration
public class AppConfig 

在测试DemoApplicationTests类进行测试

@Test
    public void componentScanTest(){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }

    }

结果如下:
Spring工作常用方法

1.2.2.1 包扫描排除过滤

配置类
appConfig

//过滤@Controller注解的组件
@ComponentScan(basePackages = {"com.cch.demo"}, excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class})})
@Configuration
public class AppConfig {
    /**
     * @return
     * @Bean 这个注解表明产生一个bean对象,像xml文件里面的<bean><bean/>标签
     */
    @Bean
    public Person person() {
        return new Person();
    }
}

测试
DemoApplicationTests

 @Test
    public void componentScanTest(){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }

    }

结果如下:
Spring工作常用方法

配置类
appConfig

//过滤指定的类
@ComponentScan(basePackages = {"com.cch.demo"}, excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = {DemoService.class})})
@Configuration
public class AppConfig {
    /**
     * @return
     * @Bean 这个注解表明产生一个bean对象,像xml文件里面的<bean><bean/>标签
     */
    @Bean
    public Person person() {
        return new Person();
    }
}

测试
DemoApplicationTests

 @Test
    public void componentScanTest(){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }

    }

结果如下
Spring工作常用方法

1.2.2.1 包扫描包含过滤

appConfig配置类如下:

//一定要把useDefaultFilters 设置为false 不然不生效
@ComponentScan(basePackages = {"com.cch.demo"}, includeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = DemoService.class)},useDefaultFilters = false)
@Configuration
public class AppConfig {
    /**
     * @return
     * @Bean 这个注解表明产生一个bean对象,像xml文件里面的<bean><bean/>标签
     */
    @Bean
    public Person person() {
        return new Person();
    }
}

测试类
DemoApplicationTests

 @Test
    public void componentScanTest(){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }

    }

测试结果如下:
包含了demoService,其他controller和repository不包含
Spring工作常用方法

1.2.2.2 包扫描包含过滤,自定义过滤器

配置类
appConfig

@ComponentScan(basePackages = {"com.cch.demo"}, includeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM,value = DemoFilter.class)},useDefaultFilters = false)
@Configuration
public class AppConfig {
    /**
     * @return
     * @Bean 这个注解表明产生一个bean对象,像xml文件里面的<bean><bean/>标签
     */
    @Bean
    public Person person() {
        return new Person();
    }

}

自定义过滤器
DemoFilter

import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;

/**
 * @Author chenchanghui
 * @date 2020/11/27 17:19
 */
public class DemoFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        ClassMetadata classMetadata = metadataReader.getClassMetadata();

        if(classMetadata.getClassName().contains("Repository")){
            return true;
        }

        return false;
    }
}

测试类
DemoApplicationTests
测试结果如下:
只包含了repository 过滤了controller 和service
Spring工作常用方法

1.3 Bean作用域

单例模式下是饿汉式立即加载,多例模式下是懒汉加载
默认情况下
@Bean 是单例模式

	@Bean
    public Person person() {
        return new Person();
    }

多例模式

    @Bean
    @Scope(value = "prototype")
    public Person person() {
        return new Person();
    }

单例懒加载

    @Bean
    @Lazy
    public Person person() {
        return new Person();
    }

1.4 @Conditional

配合@Bean ,满足条件的话,才创建对应的Bean对象
在domain包下创建

public class A {
}

在appConfig配置类中

@ComponentScan(basePackages = {"com.cch.demo"})
@Configuration
public class AppConfig {

    /**
     * 创建位置有关系,如果在person()方法下面创建,
     * 则person对象创建需要a对象的条件就不满足,
     * 则person对象将不会创建
     * @return 
     */
    @Bean
    public A a(){
        return new A();
    }


    /**
     * @return
     * @Bean 这个注解表明产生一个bean对象,像xml文件里面的<bean><bean/>标签
     */
    @Bean
    @Conditional(value = DemoCondition.class)
    public Person person() {
        return new Person();
    }
}

测试类
DemoApplicationTests

    @Test
    public void componentScanTest(){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }

    }

结果如下:
Spring工作常用方法
如果条件需要的bean “a” 在配置文件写在下方,则a对象会创建,但是person对象就不会创建,说明,spring 创建对象是从上往下创建。

二、容器中添加组件的方法

  1. 通过@Bean
  2. 通过@import (在springboot源码中常见,导入第三方组件)
  3. 通过包扫描@CompentScan +@Controller @Service @Respository @compent【我们自己写的代码常用方式】
  4. 通过实现FactoryBean接口【如sqlsessionBean】

2.1下面聊下FactoryBean这种方式

通过FactoryBean创建的对象,是调用FactoryBean接口的getObject()方法

在domain包下创建B类

@Data
public class B {

    private String id;

    public B(String id) {
        this.id = id;
    }
}

工厂实现类

public class BFactory implements FactoryBean<B> {
    @Override
    public B getObject() throws Exception {
        return new B("11111111");
    }

    @Override
    public Class<?> getObjectType() {
        return B.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

appConfig配置类

@ComponentScan(basePackages = {"com.cch.demo"})
@Configuration
public class AppConfig {
	@Bean
    public BFactory b(){
        return new BFactory();
    }
}

测试类
DemoApplicationTests

    @Test
    public void annotationConfigTest() {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        B b = (B) ctx.getBean("b");
        System.out.println(b);
    }

测试结果如下:
Spring工作常用方法

三、Bean的初始调用方法和消耗调用方法

3.1 @Bean(initMethod = “init方法名称”,destroyMethod = “destroy方法名称”)

新建Man类

public class Man {
    public void init() {
        System.out.println("init方法被调用。。。。。。。。。。");
    }
    public void destroy() {
        System.out.println("destroy方法被调用");
    }
}

appCofig配置类如下

@Configuration
public class AppConfig {

    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Man man(){
        return new Man();
    }
}

测试类
DemoApplicationTests

    @Test
    public void annotationConfigTest() {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        Man man = (Man) ctx.getBean("man");
        System.out.println(man);
        ctx.destroy();
    }

Spring工作常用方法

3.2 通过 InitializingBean和DisposableBean

domain包下
Woman类如下:

@Component
public class Woman implements InitializingBean, DisposableBean {
    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean 的 destroy 方法被调用。。。。。。。。。");
    }

    @Override
    public void afterPropertiesSet() throws Exception {

        System.out.println("InitializingBean 的 afterPropertiesSet被调用。。。。。。。。。。");
    }
}

appConfig配置类如下:

@ComponentScan(basePackages = {"com.cch.demo"})
@Configuration
public class AppConfig {
}

测试类
DemoApplicationTests

    @Test
    public void annotationConfigTest() {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        Woman woman = (Woman) ctx.getBean("woman");
        System.out.println(woman);
        ctx.destroy();
    }

测试结果如下:
Spring工作常用方法

3.3 @PostConstruct 和@PreDestory

domain包新增

@Component
public class Desk {

    @PostConstruct
    public void init(){
        System.out.println("@PostConstruct 初始化 被调用。。。。。。。。。");
    }


    @PreDestroy
    public void destroy(){
        System.out.println("@PreDestroy 注销 被调用。。。。。。。。。");
    }

}

appConfig配置类如下:

@ComponentScan(basePackages = {"com.cch.demo"})
@Configuration
public class AppConfig {
}

DemoApplicationTests测试类如下:

    @Test
    public void annotationConfigTest() {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        Desk desk = (Desk) ctx.getBean("desk");
        System.out.println(desk);
        ctx.destroy();
    }

结果如下:
Spring工作常用方法

四、读取配置文件 @Value +@PropertySource来

application.properties内容如下:

name=xxx

domain包下增加Book类

@Data
@Component
public class Book {
    @Value("${name}")
    private String name;

    @Value("#{30-3.3}")
    private double price;

}

appConfig 配置类

@ComponentScan(basePackages = {"com.cch.demo"})
@PropertySource(value = {"classpath:application.properties"})
@Configuration
public class AppConfig {
}

测试类如下:
DemoApplicationTests

   @Test
    public void annotationConfigTest() {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        Book book = (Book) ctx.getBean("book");
        System.out.println(book);
        ctx.destroy();
    }

测试结果如下:
Spring工作常用方法

五、@Profile注解使用不同环境配置

appConfig配置类如下:

@ComponentScan(basePackages = {"com.cch.demo"})
@Configuration
public class AppConfig {
    @Bean
    @Profile("test")
    public Man man(){
        return new Man();
    }

    @Bean
    @Profile("dev")
    public Woman woman(){
        return new Woman();
    }
}

DemoApplicationTests测试类如下

#JVM 参数指定环境
 -Dspring.profiles.active=dev|test|pro

Spring工作常用方法
这里指定激活dev环境,则woman对象会被创建出来,而man对象不会

    @Test
    public void componentScanTest(){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }

    }

结果如下:
Spring工作常用方法

六、自动装配使用

先说结论
自动装配首先时按照类型进行装配,若在IOC容器中发现了多个相同类型的组件,那么就按照 属性名称来进行装配

6.1对应的注入类不存在

dao包下新建DemoRepositoryInterface

@ComponentScan(basePackages = {"com.cch.demo"})
@Configuration
public class AppConfig {
}
public interface DemoRepositoryInterface {
}

service包下新建DemoService,注入DemoRepositoryInterface

@Service
public class DemoService {

    @Autowired
    private DemoRepositoryInterface demoRepositoryInterface;

}

在DemoApplicationTests测试类中执行如下测试

    @Test
    public void componentScanTest(){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }

    }

报错如下

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'demoService': Unsatisfied dependency expressed through field 'demoRepositoryInterface'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.cch.demo.dao.DemoRepositoryInterface' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

重新运行DemoApplicationTests测试方法componentScanTest
结果如下
Spring工作常用方法

在@Autowired(required = false)加上required = false 不管这个类存不存在都不影响

@Service
public class DemoService {
    @Autowired(required = false)
    private DemoRepositoryInterface demoRepositoryInterface;
}

重新运行DemoApplicationTests测试方法componentScanTest
结果如下
Spring工作常用方法

6.2 存在多个指定注入bean类型的对象

dao包下新建DemoRepository和DemoRepository2实现该接口

public class DemoRepository implements DemoRepositoryInterface{
}
public class DemoRepository2 implements DemoRepositoryInterface {
}

因为@Autowire是根据类型判断,当该类型下有多个的时候,会报错

Spring工作常用方法
核心错误如下

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'demoService': Unsatisfied dependency expressed through field 'demoRepositoryInterface'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.cch.demo.dao.DemoRepositoryInterface' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Qualifier(value=dp1), @org.springframework.beans.factory.annotation.Autowired(required=true)}

6.3 指定bean名称

为了解决该方法。需要在注入的类上写上@Qualifier(“指定注入的bean名称”)

DemoService 在注入 @Autowired增加@Qualifier(“demoRepository”)指定注入bean的名称

@Service
public class DemoService {
    @Qualifier("demoRepository")
    @Autowired
    private DemoRepositoryInterface demoRepositoryInterface;
}

重新运行DemoApplicationTests 6.1节的测试方法componentScanTest
结果成功
Spring工作常用方法

本文地址:https://blog.csdn.net/sinat_36759535/article/details/110228047

相关标签: spring