springboot学习笔记

本文详细介绍了SpringBoot的学习笔记,包括配置文件的中文乱码解决、@ConfigurationProperties、@Import、@SpringBootApplication、@ImportResource、@PropertySource、@ConfigurationProperties、@ComponentScan等注解的使用和原理,以及不同注解之间的区别和应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明

springboot:2.1.3.RELEASE
jdk:1.8

IDEA读取properties配置文件的中文乱码问题

1、在application.prperties下添加

spring.banner.charset=utf-8
server.tomcat.uri-encoding=UTF-8
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
spring.messages.encoding=UTF-8

2、修改编码

打开 File -> Settings -> Editor -> File Encodings,修改相关编码格式为UTF-8,如下图:
在这里插入图片描述

3、删除并新建application.propertie

最后,复制application.properties文件中的内容并保存到一个临时文本中,把application.properties文件删除,在原目录重新新建一个application.properties,把临时文本中的内容copy到新建的application.properties文件中,启动项目,即可正确获取中文内容

Configuration Annotation Proessor not found in classpath

1、出现spring boot Configuration Annotation Proessor not found in classpath的提示是在用了@ConfigurationProperties这个注解时,所以问题出现在ConfigurationProperties注解。
2、根据提示的not found in classpath,查询此注解的使用关于怎么指定classpath,进而查询location,spring boot1.5以上版本@ConfigurationProperties取消location注解
3、官方解决方案,Maven引入依赖

<dependency>
   <groupId> org.springframework.boot </groupId>
   <artifactId> spring-boot-configuration-processor </artifactId>
   <optional> true </optional>
</dependency>

如果添加依赖后仍不行,那就reimport一下

@import

转自:https://blog.51cto.com/4247649/2118354

是什么

通过导入的方式实现把实例加入springIOC容器中,该注解只能用在类上

三种使用方式

通过查看@Import源码可以发现@Import注解只能注解在类上,以及唯一的参数value上可以配置3种类型的值Configuration,ImportSelector,ImportBeanDefinitionRegistrar,源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
    /**
     * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
     * or regular component classes to import.
     */
    Class<?>[] value();
}

接下来就分别来看看三种方式具体使用:

基于Configuration也就是直接填对应的class数组

在bean目录下新增两个类Square和Circular如下:

/**
 * 定义一个圆形
 *
 * @author zhangqh
 * @date 2018年5月1日
 */
public class Circular {
}
/**
 * 定义一个正方形
 *
 * @author zhangqh
 * @date 2018年5月1日
 */
public class Square {
}

MainConfig注解配置中增加@Import注解如下:

@Import({Square.class,Circular.class})
@Configuration
public class MainConfig 

测试打印如下:

AnnotationConfigApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanNames = applicationContext2.getBeanDefinitionNames();
for(int i=0;i<beanNames.length;i++){
    System.out.println("bean名称为==="+beanNames[i]);
}

运行结果:

bean名称为===mainConfig
bean名称为===com.zhang.bean.Square
bean名称为===com.zhang.bean.Circular

对应的import的bean都已经加入到spring容器中了

基于基于自定义ImportSelector的使用

定义一个MyImportSelector如下:

/**
 * 定义一个我自己的ImportSelector
 *
 * @author zhangqh
 * @date 2018年5月1日
 */
public class MyImportSelector implements  ImportSelector{
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.zhang.bean.Triangle"};
    }
}

MainConfig注解配置修改如下:

@Import({Square.class,Circular.class,MyImportSelector.class})

测试结果如下:

bean名称为===mainConfig
bean名称为===com.zhang.bean.Square
bean名称为===com.zhang.bean.Circular
bean名称为===com.zhang.bean.Triangle

三角形 实例同样加入到spring容器中了

基于ImportBeanDefinitionRegistrar的使用

新建一个ImportBeanDefinitionRegistrar如下:

/**
 * 定义一个自定的ImportBeanDefinitionRegistrar
 *
 * @author zhangqh
 * @date 2018年5月1日
 */
/**
 * 定义一个自定的ImportBeanDefinitionRegistrar
 *
 * @author zhangqh
 * @date 2018年5月1日
 */
public class MyImportBeanDefinitionRegistrar  implements ImportBeanDefinitionRegistrar{
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata,
            BeanDefinitionRegistry registry) {
        // new一个RootBeanDefinition
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Rectangle.class);
        // 注册一个名字叫rectangle的bean
        registry.registerBeanDefinition("rectangle", rootBeanDefinition);
    }
}

修改MainConfig注解配置如下:

@Import({Square.class,Circular.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})

运行结果如下:

bean名称为===mainConfig
bean名称为===com.zhang.bean.Square
bean名称为===com.zhang.bean.Circular
bean名称为===com.zhang.bean.Triangle
bean名称为===rectangle

rectangle打印出来了说明我们通过ImportBeanDefinitionRegistrar注册的实例也成功加入到了spring容器了

@SpringBootApplication

许多Spring Boot开发人员喜欢他们的应用程序使用自动配置,组件扫描,并能够在他们的“应用程序类”上定义额外的配置。@SpringBootApplication可以使用单个 注释来启用这三个功能,即:

@EnableAutoConfiguration:启用Spring Boot的自动配置机制
@ComponentScan:@Component在应用程序所在的包上启用扫描
@Configuration:允许在上下文中注册额外的bean或导入其他配置类

package com.example.myapplication;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

}

@ImportResource

转自:https://www.jianshu.com/p/ec628153b7a2
将外部的配置文件加载到程序中来,比如我们定义一个beans.xml文件,里面配置了一个bean,默认情况下这个bean是不会加载到Spring容器中来的。我们需要@ImportResource注解将这个配置文件加载进来。

JavaBean

public class HelloService {}

beans.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="helloService" class="com.chentongwei.springboot.service.HelloService"></bean>
</beans>

测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class Springboot02ConfigApplicationTests {
    @Autowired
    private ApplicationContext ioc;
    @Test
    public void testHelloService() {
        boolean helloService = ioc.containsBean("helloService");
        System.out.println(helloService);
    }
}

测试结果

false

修改运行类

@SpringBootApplication
@ImportResource(locations = {"classpath:beans.xml"})
public class Springboot02ConfigApplication {

    public static void main(String[] args) {
        SpringApplication.run(Springboot02ConfigApplication.class, args);
    }
}

测试结果

true
PS:因为我们将外部的配置文件引入了,@ImportResource(locations = {“classpath:beans.xml”})

注意

@ImportResource这么看的话没卵用,因为我们现在都没了配置文件了,所以引入什么呢?其实并不然,比如:dubbo还是需要靠配置文件来配置bean的,这时候就需要此注解了。(我知道dubbo也可以按照注解来配置,我只是举个例子。),若只为了注入一个bean,完全可以采取Spring的@Bean注解。
@ImportResource并不是springboot推荐给容器添加组件的方式,SpringBoot推荐使用全注解的方式

1.创建一个config包。

2.创建一个配置类MyAppConfig.java

3.添加一个注解,@Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件

package com.example.springboot02.config;
import com.example.springboot02.service.HelloService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class MyAppConfig {
 
    //将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
    @Bean
    public HelloService helloService02(){
        System.out.println("配置类@Bean给容器中添加组件了...");
        return new HelloService();
    }
 
}
 

这时候应该是我们已经把

HelloService注册到ioc中了 而且他的id是helloService02

测试
在这里插入图片描述
在这里插入图片描述

@PropertySource

我们可以从配置文件里获取值,与JavaBean做映射。但是存在的问题是我们是从全局配置(application.yml或application.properties)里读取的。如果全部的配置都写到application里,就会显得比较臃肿,同时也不太好理解和维护。可以将一个文件拆分为多个,此时使用@PropertySource即可解决问题,@PropertySource 用于加载指定的配置文件

person.properties

person.lastName=李四
person.age=25
person.birth=2017/12/15
person.boss=true
person.maps.key1=value1
person.maps.key2=value2
person.lists=a,b,c
person.dog.name=dog
person.dog.age=2

Javabean

@PropertySource(value = {"classpath:person.properties"})
@ConfigurationProperties(prefix = "person")
@Component
public class Person {
    private String lastName;
    private Integer age;
    private boolean isBoss;
    private Date birth;

    private Map<String, Object> maps;
    private List<Object> lists;
    private Dog dog;
    ...setter/getter/toString...
}

这样一个注解(@PropertySource(value = {“classpath:person.properties”}))就可以搞定不在主配置里读取,按照不同的功能模块划分出不同的配置文件
实例:https://blog.youkuaiyun.com/wangmx1993328/article/details/81005170
https://www.jb51.net/article/130471.htm?tdsourcetag=s_pcqq_aiomsg
在这里插入图片描述
@PropertySource 加载指定配置文件
@ConfigurationProperties 表示 告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
@ConfigurationProperties (prefix = “user”) 默认从全局配置文件中获取值然后进行注入
prefix = “user” 表示 将配置文件中key为user的下面所有的属性与本类属性进行一一映射注入值,如果配置文件 不存在"user"的key,则不会为POJO注入值,属性值仍然为默认值
@ConfigurationProperties(prefix = “remote”, ignoreUnknownFields = false):ignoreUnknownFields是用来告诉SpringBoot在有属性不能匹配到声明的域时抛出异常。
@Component 将本来标识为一个Spring 组件,因为只有是容器中的组件,容器才会为@ConfigurationProperties提供此注入功能
@PropertySource (value = {“classpath:user.properties”}) 指明加载类路径下的哪个配置文件来注入值

package com.lct.wmx.damain;
 
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
 
import javax.validation.constraints.Email;
import java.util.Date;
import java.util.List;
import java.util.Map;
 
/**
 * Created by Administrator on 2018/7/11 0011.
 * 用户···实体
 *
 * @ConfigurationProperties 表示 告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
 * @ConfigurationProperties (prefix = "user") 默认从全局配置文件中获取值然后进行注入
 * prefix = "user" 表示 将配置文件中key为user的下面所有的属性与本类属性进行一一映射注入值,如果配置文件中
 * 不存在"user"的key,则不会为POJO注入值,属性值仍然为默认值
 * <p/>
 * @Component 将本来标识为一个Spring 组件,因为只有是容器中的组件,容器才会为@ConfigurationProperties提供此注入功能
 * @PropertySource (value = {"classpath:user.properties"}) 指明加载类路径下的哪个配置文件来注入值
 */
@PropertySource(value = {"classpath:user.properties"})
@Component
@ConfigurationProperties(prefix = "user")
public class User {
    private Integer id;
    private String lastName;
    private Integer age;
    private Date birthday;
    private List<String> colorList;
    private Map<String, String> cityMap;
    private Dog dog;
 
    public Integer getAge() {
        return age;
    }
 
    public void setAge(Integer age) {
        this.age = age;
    }
 
    public Date getBirthday() {
        return birthday;
    }
 
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
 
    public Map<String, String> getCityMap() {
        return cityMap;
    }
 
    public void setCityMap(Map<String, String> cityMap) {
        this.cityMap = cityMap;
    }
 
    public List<String> getColorList() {
        return colorList;
    }
 
    public void setColorList(List<String> colorList) {
        this.colorList = colorList;
    }
 
    public Dog getDog() {
        return dog;
    }
 
    public void setDog(Dog dog) {
        this.dog = dog;
    }
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getLastName() {
        return lastName;
    }
 
    public void setLastName(String name) {
        this.lastName = name;
    }
 
    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", id=" + id +
                ", lastName='" + lastName + '\'' +
                ", birthday=" + birthday +
                ", colorList=" + colorList +
                ", cityMap=" + cityMap +
                ", dog=" + dog +
                '}';
    }
}

资源配置文件
在这里插入图片描述

user.id=111
user.lastName=张无忌
user.age=120
user.birthday=2018/07/11
user.colorList=red,yellow,green,blacnk
user.cityMap.mapK1=mapV1
user.cityMap.mapK2=mapV2
user.dog.id=7523
user.dog.name=狗不理
user.dog.age=3

测试

package com.lct.wmx;
 
import com.lct.wmx.damain.Dog;
import com.lct.wmx.damain.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
 
import javax.annotation.Resource;
 
/**
 * SpringBoot单元测试
 * 可以在测试期间很方便的类似编码一样进行自动注入等容器的功能
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class HelloWorldQuickApplicationTests {
 
    /**
     * 因为POJO类使用了@Component注解,就是Spring一个组件,交由了Spring容器注入值
     * 所以使用@Autowired或者@Resource,DI注入在取值即可
     */
    @Resource
    private User user;
 
    @Test
    public void contextLoads() {
        System.out.println("------------------------------********************--------------------------------------------");
        System.out.println("·······················" + user);
    }
}

在这里插入图片描述
如果不是在测试类是使用配置文件,则直接在使用配置文件的类上添加EnableConfigurationProperties(与配置文件对应的类名.class)
实例:https://www.jb51.net/article/130471.htm?tdsourcetag=s_pcqq_aiomsg
在这里插入图片描述
配置文件

remote.uploadFilesUrl=/resource/files/
remote.uploadPicUrl=/resource/pic/

新建一个配置类RemoteProperties.java

@Configuration
@ConfigurationProperties(prefix = "remote", ignoreUnknownFields = false)
@PropertySource("classpath:config/remote.properties")
@Data
@Component
public class RemoteProperties {
  private String uploadFilesUrl;
  private String uploadPicUrl;
}

使用
在想要使用配置文件的方法所在类上表上注解EnableConfigurationProperties(RemoteProperties.class)
并自动注入。在方法中使用 remoteProperties.getUploadFilesUrl()就可以拿到配置内容了。

@EnableConfigurationProperties(RemoteProperties.class)
@RestController
public class TestService{
  @Autowired
  RemoteProperties remoteProperties;
 
  public void test(){
    String str = remoteProperties.getUploadFilesUrl();
    System.out.println(str);
  }
}

@ConfigurationProperties

https://blog.youkuaiyun.com/XU906722/article/details/81517429
https://www.cnblogs.com/liaojie970/p/8043150.html
@ConfigurationProperties可以读取配置配置文件的信息并自动封装成实体类
如果只是某个业务中需要获取配置文件中的某项值或者设置具体值,可以使用@Value;
如果一个JavaBean中大量属性值要和配置文件进行映射,可以使用@ConfigurationProperties;

配置文件

#private String lastName;
#private Integer age;
#private Boolean boss;
#private Date birth;
#
#private Map<String,Object> maps;
#private List<Object> lists;
 
#配置person的属性值
person.last-name=zhangsan
person.age=18
person.boss=false
person.birth=1992/02/20
person.maps.k1=v1
person.maps.k2=111
person.lists=a,b,c
 

实体类

/*
* 将配置文件application.properties中配置的每一个属性值映射到当前类的属性中;
* @ConfigurationProperties:告诉springboot将本类中所有属性和配置文件中相关的配置进行绑定;
* prefix="person":指出将配置文件中person下的所有属性进行一一映射;
*
* 注意:只有当前这个类是容器中的组件时,才可以用容器提供的@ConfigurationProperties功能;
*
* */
 
@Component
@ConfigurationProperties(prefix="person")
public class Person {
 
    private String lastName;
    private Integer age;
    private Boolean boss;
    private Date birth;
 
    private Map<String,Object> maps;
    private List<Object> lists;
 
    @Override
    public String toString() {
        return "Person{" +
                "lastName='" + lastName + '\'' +
                ", age=" + age +
                ", boss=" + boss +
                ", birth=" + birth +
                ", maps=" + maps +
                ", lists=" + lists +
                '}';
    }
 
   getter...
   setter...
 
}

测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestApplicationConfig {
    @Autowired
    Person person;
 
    @Test
    public void testPersonProperties(){
        System.out.println(person);
    }
}

运行结果

在这里插入图片描述
我们还可以把@ConfigurationProperties还可以直接定义在@bean的注解上,这是bean实体类就不用@Component和@ConfigurationProperties了
下面的例子是ConnectionSettings 类对应配置文件

@SpringBootApplication
public class DemoApplication{

    //...

    @Bean
    @ConfigurationProperties(prefix = "connection")
    public ConnectionSettings connectionSettings(){
        return new ConnectionSettings();

    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

然后我们需要使用的时候就直接这样子注入

@RestController
@RequestMapping("/task")
public class TaskController {

@Autowired ConnectionSettings conn;

@RequestMapping(value = {"/",""})
public String hellTask(){
    String userName = conn.getUsername();     
    return "hello task !!";
}

}

如果发现@ConfigurationPropertie不生效,有可能是项目的目录结构问题,

你可以通过@EnableConfigurationProperties(ConnectionSettings.class)来明确指定需要用哪个实体类来装载配置信息

@Configuration
@EnableConfigurationProperties(ConnectionSettings.class)
 public class MailConfiguration { 
    @Autowired private MailProperties mailProperties; 

    @Bean public JavaMailSender javaMailSender() {
      // omitted for readability
    }
 }

@Value给属性设置值

编写JavaBean
@Component
//@ConfigurationProperties(prefix="person")
public class Person {
 
    @Value("${person.last-name}") // 从配置文件中获取值
    private String lastName;
 
    @Value("#{2*8}")  // spring表达式
    private Integer age;
 
    @Value("true") // boolean值
    private Boolean boss;
    private Date birth;
 
    private Map<String,Object> maps;
    private List<Object> lists;
 
    @Override
    public String toString() {
        return "Person{" +
                "lastName='" + lastName + '\'' +
                ", age=" + age +
                ", boss=" + boss +
                ", birth=" + birth +
                ", maps=" + maps +
                ", lists=" + lists +
                '}';
    }
}

运行结果

在这里插入图片描述

@ConfigurationProperties和@Value对比

@ConfigurationProperties@Value
功能根据配置文件中设置的属性,批量注入属性值单个指定值
松散语法支持(lastName可以写作last-name、last_name)不支持
SpEL(Spring表达式)不支持支持
JSR303数据校验支持(可以通过@Email等注解校验属性值是否符合要求)不支持
复杂类型封装(Map、List等类型)支持不支持

@Import、@ImportResource、@PropertySource、@ConfigurationProperties

参考:https://blog.youkuaiyun.com/u010469514/article/details/81263711

@Import注解是通过导入的方式实现把实例加入springIOC容器中。引入带有@Configuration的java类,类似于spring配置文件里的import标签,将多个配置文件导入到一个主配置文件里
@ImportResource是引入spring配置文件.xml,管理配置的bean

@PropertySource注解自定义配置文件名称,多用于配置文件与实体属性映射。注解将properties配置文件中的值存储到Spring的 Environment中,Environment接口提供方法去读取配置文件中的值,参数是properties文件中定义的key值

@ConfigurationProperties是Spring Boot的注解,用来批量加载配置文件

@EnableAutoConfiguration

转自:https://blog.youkuaiyun.com/love_dl_forever/article/details/78859508
启用Spring应用程序上下文的自动配置,尝试猜测和配置您可能需要的bean。自动配置类通常基于类路径和定义的bean应用。例如,如果你有 tomcat-embedded.jar在您的类路径中,你可能会想要一个TomcatEmbeddedServletContainerFactory(除非你定义自己的EmbeddedServletContainerFactory bean)。
当使用SpringBootApplication时,上下文的自动配置将自动启用并添加此注释,因此不会产生额外的效果。
自动配置尝试尽可能地智能化,并且在您定义更多自己的配置时将会备份。您总是可以手工排除()任何您不想应用的配置(如果您无法访问它们的话)。您也可以通过spring. autoconfigure将它们排除。排除属性。在用户定义的bean被注册之后,自动配置总是被应用。
用@ enableautoconfiguration注释的类的包,通常通过@ springbootapplication,具有特殊的意义,经常被用作“默认”。例如,它将用于扫描@ entity类。通常建议在根包中放置@ enableautoconfiguration(如果您不使用@ springbootapplication),以便可以搜索所有子包和类。
自动配置类是常规的Spring配置bean。它们使用SpringFactoriesLoader机制(对该类进行键控)定位。通常,自动配置bean都是“有条件bean”(通常使用@ conditionalonclass和@ conditionalonmissingbean注释)。

@Configuration

转自:https://www.cnblogs.com/duanxz/p/7493276.html

1、是什么

从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

注意:@Configuration注解的配置类有如下要求

@Configuration不可以是final类型;
@Configuration不可以是匿名类;
嵌套的configuration必须是静态类。

总结

 @Configuation等价于<Beans>........</Beans>
 @Bean等价于<bean>.......</bean>
 @ComponentScan等价于<context:component-scan base-package=”com.dxz.demo”/>

@Configuation加载Spring方法
@Configuration配置spring并启动spring容器

@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的,作用为:配置spring容器(应用上下文)

2、用@Configuration加载spring

  • @Configuration配置spring并启动spring容器
  • @Configuration启动容器+@Bean注册Bean
  • @Configuration启动容器+@Component注册Bean
  • 使用 AnnotationConfigApplicationContext 注册 AppContext 类的两种方法
  • 配置Web应用程序(web.xml中配置AnnotationConfigApplicationContext)
2.1@Configuration配置spring并启动spring容器

@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的<beans ,作用为:配置spring容器(应用上下文)

package com.dxz.demo.configuration;

import org.springframework.context.annotation.Configuration;

@Configuration
public class TestConfiguration {
    public TestConfiguration() {
        System.out.println("TestConfiguration容器启动初始化。。。");
    }
}

相当于:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd" default-lazy-init="false">


</beans>

主方法进行测试:

package com.dxz.demo.configuration;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestMain {
    public static void main(String[] args) {

        // @Configuration注解的spring容器加载方式,用AnnotationConfigApplicationContext替换ClassPathXmlApplicationContext
        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);

        // 如果加载spring-context.xml文件:
        // ApplicationContext context = new
        // ClassPathXmlApplicationContext("spring-context.xml");
    }
}

从运行主方法结果可以看出,spring容器已经启动了:
在这里插入图片描述

2.2@Configuration启动容器+@Bean注册Bean

@Bean标注在方法上(返回某个实例的方法),等价于spring的xml配置文件中的,作用为:注册bean对象

bean类:

package com.dxz.demo.configuration;

public class TestBean {

    private String username;
    private String url;
    private String password;

    public void sayHello() {
        System.out.println("TestBean sayHello...");
    }

    public String toString() {
        return "username:" + this.username + ",url:" + this.url + ",password:" + this.password;
    }

    public void start() {
        System.out.println("TestBean 初始化。。。");
    }

    public void cleanUp() {
        System.out.println("TestBean 销毁。。。");
    }
}

配置类:

package com.dxz.demo.configuration;

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

@Configuration
public class TestConfiguration {
    public TestConfiguration() {
        System.out.println("TestConfiguration容器启动初始化。。。");
    }

    // @Bean注解注册bean,同时可以指定初始化和销毁方法
    // @Bean(name="testBean",initMethod="start",destroyMethod="cleanUp")
    @Bean
    @Scope("prototype")
    public TestBean testBean() {
        return new TestBean();
    }
}

主方法测试类:

package com.dxz.demo.configuration;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestMain {
    public static void main(String[] args) {

        // @Configuration注解的spring容器加载方式,用AnnotationConfigApplicationContext替换ClassPathXmlApplicationContext
        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);

        // 如果加载spring-context.xml文件:
        // ApplicationContext context = new
        // ClassPathXmlApplicationContext("spring-context.xml");
        
         //获取bean
        TestBean tb = (TestBean) context.getBean("testBean");
        tb.sayHello();
    }
}

结果:
在这里插入图片描述
注:
(1)、@Bean注解在返回实例的方法上,如果未通过@Bean指定bean的名称,则默认与标注的方法名相同;
(2)、@Bean注解默认作用域为单例singleton作用域,可通过@Scope(“prototype”)设置为原型作用域;
(3)、既然@Bean的作用是注册bean对象,那么完全可以使用@Component、@Controller、@Service、@Ripository等注解注册bean,当然需要配置@ComponentScan注解进行自动扫描。

2.2.1@Bean下管理bean的生命周期

可以使用基于 Java 的配置来管理 bean 的生命周期。@Bean 支持两种属性,即 initMethod 和destroyMethod,这些属性可用于定义生命周期方法。在实例化 bean 或即将销毁它时,容器便可调用生命周期方法。生命周期方法也称为回调方法,因为它将由容器调用。使用 @Bean 注释注册的 bean 也支持 JSR-250 规定的标准 @PostConstruct 和 @PreDestroy 注释。如果您正在使用 XML 方法来定义 bean,那么就应该使用 bean 元素来定义生命周期回调方法。以下代码显示了在 XML 配置中通常使用 bean 元素定义回调的方法。

@Configuration
@ComponentScan(basePackages = "com.dxz.demo.configuration")
public class TestConfiguration {
    public TestConfiguration() {
        System.out.println("TestConfiguration容器启动初始化。。。");
    }

    //@Bean注解注册bean,同时可以指定初始化和销毁方法
    **@Bean(name="testBean",initMethod="start",destroyMethod="cleanUp")
    @Scope("prototype")**
    public TestBean testBean() {
        return new TestBean();
    }
}

启动类

public class TestMain {
    public static void main(String[] args) {

        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);

        TestBean tb = (TestBean) context.getBean("testBean");
        tb.sayHello();
        System.out.println(tb);
        
        TestBean tb2 = (TestBean) context.getBean("testBean");
        tb2.sayHello();
        System.out.println(tb2);
    }
}

结果:
在这里插入图片描述
分析:

结果中的1:表明initMethod生效

结果中的2:表明@Scope(“prototype”)生效

2.3@Configuration启动容器+@Component注册Bean

bean类:

package com.dxz.demo.configuration;

import org.springframework.stereotype.Component;

//添加注册bean的注解
@Component
public class TestBean {

    private String username;
    private String url;
    private String password;

    public void sayHello() {
        System.out.println("TestBean sayHello...");
    }

    public String toString() {
        return "username:" + this.username + ",url:" + this.url + ",password:" + this.password;
    }

    public void start() {
        System.out.println("TestBean 初始化。。。");
    }

    public void cleanUp() {
        System.out.println("TestBean 销毁。。。");
    }
}

配置类:

package com.dxz.demo.configuration;

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

@Configuration
//添加自动扫描注解,basePackages为TestBean包路径
@ComponentScan(basePackages = "com.dxz.demo.configuration")
public class TestConfiguration {
    public TestConfiguration() {
        System.out.println("TestConfiguration容器启动初始化。。。");
    }

    /*// @Bean注解注册bean,同时可以指定初始化和销毁方法
    // @Bean(name="testNean",initMethod="start",destroyMethod="cleanUp")
    @Bean
    @Scope("prototype")
    public TestBean testBean() {
        return new TestBean();
    }*/
}

主方法测试获取bean对象

package com.dxz.demo.configuration;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestMain {
    public static void main(String[] args) {

        // @Configuration注解的spring容器加载方式,用AnnotationConfigApplicationContext替换ClassPathXmlApplicationContext
        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);

        // 如果加载spring-context.xml文件:
        // ApplicationContext context = new
        // ClassPathXmlApplicationContext("spring-context.xml");
        
         //获取bean
        TestBean tb = (TestBean) context.getBean("testBean");
        tb.sayHello();
    }
}

sayHello()方法都被正常调用。
在这里插入图片描述

2.4使用 AnnotationConfigApplicationContext 注册 AppContext 类的两种方法
2.4.1配置类的注册方式是将其传递给 AnnotationConfigApplicationContext 构造函数
public static void main(String[] args) {

        // @Configuration注解的spring容器加载方式,用AnnotationConfigApplicationContext替换ClassPathXmlApplicationContext
        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);

        //获取bean
        TestBean tb = (TestBean) context.getBean("testBean");
        tb.sayHello();
    }
2.4.2AnnotationConfigApplicationContext 的register 方法传入配置类来注册配置类
public static void main(String[] args) {
  ApplicationContext ctx = new AnnotationConfigApplicationContext();
  ctx.register(AppContext.class)
}
2.5配置Web应用程序(web.xml中配置AnnotationConfigApplicationContext)

过去,您通常要利用 XmlWebApplicationContext 上下文来配置 Spring Web 应用程序,即在 Web 部署描述符文件 web.xml 中指定外部 XML 上下文文件的路径。XMLWebApplicationContext 是 Web 应用程序使用的默认上下文类。以下代码描述了 web.xml 中指向将由 ContextLoaderListener 监听器类载入的外部 XML 上下文文件的元素。

<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <servlet>
    <servlet-name>sampleServlet</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    </servlet>

</web-app>

现在,您要将 web.xml 中的上述代码更改为使用 AnnotationConfigApplicationContext 类。切记,XmlWebApplicationContext 是 Spring 为 Web 应用程序使用的默认上下文实现,因此您永远不必在您的web.xml 文件中显式指定这个上下文类。现在,您将使用基于 Java 的配置,因此在配置 Web 应用程序时,需要在web.xml 文件中指定 AnnotationConfigApplicationContext 类。上述代码将修改如下:

<web-app>
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.
            support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            demo.AppContext
        </param-value>
    </context-param>
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <servlet>
    <servlet-name>sampleServlet</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.
            support.AnnotationConfigWebApplicationContext
        </param-value>
    </init-param>
    </servlet>
</web-app>

以上修改后的 web.xml 现在定义了 AnnotationConfigWebApplicationContext 上下文类,并将其作为上下文参数和 servlet 元素的一部分。上下文配置位置现在指向 AppContext 配置类。这非常简单。下一节将演示 bean 的生命周期回调和范围的实现。

@ComponentScan

转自:https://blog.51cto.com/4247649/2118342

是什么

@ComponentScan主要就是定义扫描的路径,从扫描路径中找出标识了需要装配的类,并将类自动装配到spring的bean容器中

怎么用

做过web开发的同学一定都有用过@Controller,@Service,@Repository注解,查看其源码你会发现,他们中有一个共同的注解@Component,没错@ComponentScan注解默认就会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中,好下面咱们就先来简单演示一下这个例子

在包com.zhang.controller下新建一个UserController带@Controller注解如下:

package com.zhang.controller;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
}

在包com.zhang.service下新建一个UserService带@Service注解如下:

package com.zhang.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
}

在包com.zhang.dao下新建一个UserDao带@Repository注解如下:

package com.zhang.dao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
}

新建一个配置类如下:

/**
 * 主配置类  包扫描com.zhang
 *
 * @author zhangqh
 * @date 2018年5月12日
 */
@ComponentScan(value="com.zhang")
@Configuration
public class MainScanConfig {
}

新建测试方法如下:

AnnotationConfigApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(MainScanConfig.class);
        String[] definitionNames = applicationContext2.getBeanDefinitionNames();
        for (String name : definitionNames) {
            System.out.println(name);
}

运行结果如下:

mainScanConfig
userController
userDao
userService

@ComponentScan ,可以加载多个包下spring管理的bean,每个用分号“”和逗号,隔开,如果没有组件扫描注解,则可能会报 无法注入bean 的错误
@ComponentScan(basePackages={“dao”,“service”}),dao、service分别是2个包名。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值