Spring学习

Spring核心

组件扫描 component scanning

@ComponentScan注解是一个Spring的注解,用于扫描包上的注解将组件加载到IOC容器中。

作用:扫描被@Controller、@Service、@Repository、@Component等注解标注的类。

@ComponentScan注解只能使用在有@Configuration配置注解的地方,因为component-scan标签必须存在于xml配置文件中;而在脱离xml使用时,需要使用带有在@Configuration配置注解上。

简而言之

@Configuration = xml 文件

@ComponentScan用来代替xml文件中的配置control、Service、Repository、Component的配置语句

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

例如以上语句就扫描了entity包下的所有类,用@ComponentScan代替就是

@Configuration
@ComponentScan(basePackages = {"com.thg.entity"})
public class Config {

}

Component注解

把普通pojo实例化到spring容器中,相当于配置文件中的

<bean id="" class=""/>

使用方法:

  • 在pojo类上加入@Component关键字
  • 如果使用@Configuration配置,则加入@ComponentScan(basePackages = {“com.thg.entity”})扫描包
  • 如果使用xml配置,则加入 <context:component-scan base-package=“com.thg.entity”/>

Autowire注解

如果说Component=

那么Autowire=<construct-args + <propority

一般@Autowire配合@Component一起使用

  • @Component注册bean
  • @Autowire注入依赖

Autowire有三种注入方式

  • 属性注入
  • setter注入
  • 构造器注入

Qualifier 注解

@Qualifier一般与@Autowire一起用,当我们需要注入的对象有多个时,为了避免歧义装配错了,采用@Qualifier指明需要装配的bean id/name

public class Profile {
   @Autowired
   @Qualifier("student1")
   private Student student;
   public Profile(){
      System.out.println("Inside Profile constructor." );
   }
   public void printAge() {
      System.out.println("Age : " + student.getAge() );
   }
   public void printName() {
      System.out.println("Name : " + student.getName() );
   }
}

Bean注解

Bean注解和Component有些类似

Component的作用是标明该类需要被注入,然后使用ComponentScan扫描注入

而Bean注解也是注入,但是他是放在Config类中,去处理某些无法由Component处理的注入的情形

  • 内部类,无法Component
  • Component一个类对应一个bean,如果一个类需要多个Component的时候,使用@bean

比如我需要注入一个Map,显然我不可能跑源码里去注入Map

如果去写xml又显得头重脚轻多此一举,这时bean就起到作用了

@Configuration
@ComponentScan(basePackages = {"com.thg.entity"})
public class Config {

 @Bean
 public Map<String,String> getMap(){
     Map<String,String> map = new HashMap<>();
     map.put("no1","thg");
     map.put("no2","thh");
     System.out.println("map is 注入");
     return map;
 }
}

取别名

如上,@bean会将getMap注入到ioc容器中,如果你想换个名字,这样就行了

@Bean(name = "map")

创建函数及销毁函数

 @Bean(initMethod = "init", destroyMethod = "cleanup" )

Config配置

我们使用@Configuration去代替xml文件

@ComponentScan

  • 作用:用来扫描control、Service、Repository、Component的配置语句
  • 等价于<context:component-scan base-package=“xxx”/>
  • 代码位置:放在Config类上

@Import

  • 作用:@import 注解允许从另一个配置类中加载 @Bean 定义。

  • 代码位置:放在Config类上

@Profile

指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件

就比如数据库连接池这些,在不同环境下加载不同的属性

需要在主函数拿到context之后指定即可

applicationContext.getEnvironment().setActiveProfiles("dev","master");

Spring Boot

SpringBootApplication核心注解

源码如下

package org.springframework.boot.autoconfigure;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
  @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
  @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
   ......
}

package org.springframework.boot;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {

}

简而言之,SpringBootApplication注解等效于下面三个注解的合集

  • @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制
  • @ComponentScan: 扫描被@Component (@Service,@Controller)注解的 bean,注解默认会扫描该类所在的包下所有的类。
  • @Configuration:允许在 Spring 上下文中注册额外的 bean 或导入其他配置类

后两个注解都很熟悉,我们来康康@EnableAutoConfiguration

@EnableAutoConfiguration

默认会扫描与项目启动类同级或者更低级目录下的所有使用@Configuration注解的类

意思就是@Configuration最好放在同级别下,否则你要加入@Improt把你写的config加入进来

config实现的三种方式

  • 直接在SpringBootApplication上加入你需要的东西,因为SpringBootApplication本质就是一个config类
  • 在SpringBootApplication的统计目录或者下级目录下实现一个config类,并用@Configuration标注
  • 在别的地方配置Config 然后使用@Import加入SpringBootApplication

Application配置文件

springboot引入了application.properties和application.yaml来简化配置过程

spring:
  application:
    name: "thg"
  datasource:
    url: jdbc:mysql://sh-cynosdbmysql-grp-bbhdi89q.sql.tencentcdb.com:21590/pic?serverTimezone=UTC
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: thgXXXXXX!
server:
  port: 8081

就比如上面的配置,不需要注入任何的bean,就可以直接在代码中使用

    @Autowired
    JdbcTemplate jdbcTemplate;

属性嵌套

app.name=MyApp
app.description=${app.name} 

Yaml文件

基本语法

对象:

father:
  child1: Jack
  child2: Bob

数组:

animals:
  - Cat
  - Dog
  - Goldfish

或者

animals: [ 'Cat', 'Dog', 'Goldfish' ]

null值:

用~表示null

@ConfigurationProperties实现自动装配

@ConfigurationProperties(prefix = "my-person")
@Component
@Data
public class Person {
    private String userName;
    private Boolean boss;
    private Date birth;
    private Integer age;
    private Pet pet;
    private String[] interests;
    private List<String> animal;
    private Map<String, Object> score;
    private Set<Double> salarys;
    private Map<String, List<Pet>> allPets;
}
my-person:
  user-name: CodeTiger
  boss: true
  birth: 1996/11/29
  # 可以使用random来生成各种不同类型的随机值
  age: ${random.int}
  pet:
    name: tomcat
    weight: 100
  interests: [basketball, football]
  animal:
    - jerry
    - tom
  score:
    english:
      first: 30
      second: 40
      third: 50
    math: [131,140,148]
    chinese: {first: 128, second: 136}
    salarys: [3999,4999.98,5999.99]
    allPets:
      sick:
        - {name: tom}
        - {name: jerry,weight: 47}
      health: [{name: mario,weight: 47}]

注意:@ConfigurationProperties的本质是使用setter注入,所以必须要有setter方法不然没法注入

关于引入其他yaml文件的问题

我们可以注意到,当我们要引用其他配置文件时,使用@PropertySource注解来引用

但是这个注解无法配置yaml文件,所以有两种解决方案

  • 其他配置文件全部用properties来实现
  • 自己实现factory来转换yaml

自定义factory如下

import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;
import org.springframework.lang.Nullable;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

public class YamlPropertySourceFactory implements PropertySourceFactory {
    @Override
    public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException {
        Properties propertiesFromYaml = loadYamlIntoProperties(resource);
        String sourceName = name != null ? name : resource.getResource().getFilename();
        return new PropertiesPropertySource(sourceName, propertiesFromYaml);
    }

    private Properties loadYamlIntoProperties(EncodedResource resource) throws FileNotFoundException {
        try {
            YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
            factory.setResources(resource.getResource());
            factory.afterPropertiesSet();
            return factory.getObject();
        } catch (IllegalStateException e) {
            // for ignoreResourceNotFound
            Throwable cause = e.getCause();
            if (cause instanceof FileNotFoundException)
                throw (FileNotFoundException) e.getCause();
            throw e;
        }
    }
}

使用时:

@Component
@PropertySource(value = "my.yaml" , factory = YamlPropertySourceFactory.class)
@ConfigurationProperties(prefix = "user")
@Data
public class User {
    private int age;
    private String name;
}

Spring配置

Maven依赖

spring核心

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.3.20</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.3.20</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.20</version>
        </dependency>

SpringBoot核心

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

JDBC以及mysql

        //用spring时用这个
				<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.20</version>
        </dependency>

				//用springboot用这个
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>

配置JDBC

spring其实经历了从xml->config->springboot的过程,所以配置数据库连接也有三种方式

xml原始版

<!-- 1.数据库配置 -->
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${driverClassName}"></property>
		<property name="url" value="${url}"></property>
		<property name="password" value="${password}"></property>
		<property name="username" value="${username}"></property>
	</bean>

	<!-- 2.配置JDBC帮助类 -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>

	<!-- 3.加载资源文件 -->
	<bean id="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:spring/dbconfig.properties</value>
			</list>
		</property>
	</bean>
	<bean id="demo" class="com.dmeo.jdbc.JDBCTest"></bean>

config版本

我们看到xml配置中

  • propertyConfigurer可以用 @PropertySource(“classpath:/dbconfig.properties”)代替
url=jdbc:mysql://sh-cynosdbmysql-grp-bbhdi89q.sql.tencentcdb.com:21590/pic?serverTimezone=UTC
driverClassName=com.mysql.jdbc.Driver
password=thg1998913!
user=root
@Configuration
@ComponentScan(basePackages = {"com.thg.entity"})
@PropertySource(value = {"dbconfig.properties"})
public class Config {
    @Autowired
    DriverManagerDataSource dataSource;
    @Bean
    public DriverManagerDataSource dataSource(@Value("${url}") String url,@Value("${driverClassName}") String driverClassName,@Value("${user}")String username, @Value("${password}")String passwd){
        DriverManagerDataSource database = new DriverManagerDataSource() ;
        database.setUrl(url); //设置url
        database.setDriverClassName(driverClassName);
        database.setUsername(username); //设置账号
        database.setPassword(passwd); //设置密码
        return database;
    }
    @Bean
    public JdbcTemplate jdbcTemplate(){
        return new JdbcTemplate(dataSource);
    }
}

这里有一个需要注意的地方

就是@Value(“${user}”)String username

我开始是使用@Value(“${username}”)String username

后面一直连接不上的原因是无论你怎么改变dbconfig.properties的内容始终username永远定格在"thg"

我就怀疑是spring内置了一个变量叫username,导致我@Value出来的不是我properties文件中的内容

于是我将username改为user后发现可以成功连接上

springboot配置

我们知道springboot自动装配

使用application.properties配置

spring.datasource.url=jdbc:mysql://sh-cynosdbmysql-grp-bbhdi89q.sql.tencentcdb.com:21590/pic?serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.password=thg1998913!
spring.datasource.username=root

使用yaml配置其实是一样的不在累叙

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值