Spring的常见用法

2 篇文章 0 订阅
1 篇文章 0 订阅

Spring的常见用法


1、spring常见实现加载xml配置的入口

​ Spring提供了ApplicationContext接口的几种实现方式。在独立应用程序中,通常创建ClassPathXmlApplicationContextFileSystemXmlApplicationContext的实例。


2、注入bean的方式

​ 基于构造函数的依赖注入、基于 Setter 的依赖注入

  • 1、xml中配置(构造函数实例化、静态工厂实例化、实例工厂方法实例化)
  • 2、自动注入
  • 3、方法注入(实现ApplicationContextAware接口)

3、自动装配的方式

自动装配的模式:

  • no:xml配置
  • byName:根据属性名称 (@Resource
  • byType:根据属性类型(@Autowired
  • constructor:根据构造函数匹配

4、bean的作用域

  • singleton:只创建一个bean的实例
  • prototype:每个引用都创建一个bean的实例(例如:A类注入C类,B类也注入C类,C类一共创建了2个bean的实例)
  • requestsessionglobalSessionapplicationwebsocket范围仅在使用网络感知的 Spring ApplicationContext实现(例如XmlWebApplicationContext)时可用。

5、bean初始化和销毁方法

5.1 初始化方法:

  • 自定义初始化方法添加注解(@PostConstruct
  • 实现InitializingBean回调接口定义的afterPropertiesSet()
  • xml配置中自定义配置的init()方法(init-method="init")

5.2销毁方法:

  • 自定义方法添加注解(@PreDestroy
  • 实现DisposableBean回调接口定义的destroy()
  • xml配置中自定义配置的destroy()方法(destroy-method="cleanup"

6、@Autowired 的用法

  • 1、应用于构造函数
  • 2、应用于具有任意名称和/或多个参数的方法
  • 3、应用于字段,甚至将其与构造函数混合使用
  • 4、应用于字段
  • 5、添加到需要该类型数组的字段或方法中(如果希望数组或列表中的项按特定顺序则目标bean可实现org.springframework.core.Ordered 或者接口或使用@Order或标准@Priority 注解)

7、使用@Primary 微调基于 Comments 的自动装配

​ 由于按类型自动布线可能会导致多个候选对象,因此通常有必要对选择过程进行更多控制。实现此目的的一种方法是使用 Spring 的@PrimaryComments。 @Primary表示当多个 bean 可以自动连接到单值依赖项的候选对象时,应优先考虑特定的 bean。如果候选对象中仅存在一个“主” bean,它将是自动装配的值。

8、用限定符(@Qualifier)微调基于 Comments 的自动装配

​ 当可以确定一个主要候选对象时,@Primary是在几种情况下按类型使用自动装配的有效方法。当需要对选择过程进行更多控制时,可以使用 Spring 的@QualifierComments。您可以将限定符值与特定的参数相关联,从而缩小类型匹配的范围,以便为每个参数选择特定的 bean.

  • 1、字段上指定
	@Autowired
    @Qualifier("main")
    private MovieCatalog movieCatalog;
  • 2、各个构造函数参数或方法参数上指定
  private MovieCatalog movieCatalog;

    private CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public void prepare(@Qualifier("main")MovieCatalog movieCatalog,
            CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }
  • 3、自定义

自定义限定符 Comments。只需定义一个 Comments 并在定义中提供@QualifierComments:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {

    String value();
}
 @Autowired
    @Genre("Action")
    private MovieCatalog actionCatalog;

    private MovieCatalog comedyCatalog;

    @Autowired
    public void setComedyCatalog(@Genre("Comedy") MovieCatalog comedyCatalog) {
        this.comedyCatalog = comedyCatalog;
    }

9、@Resource

@Resource具有名称属性,默认情况下,Spring 将该值解释为要注入的 Bean 名称。换句话说,它遵循* by-name *语义.

​ 在未指定@Resource且未指定显式名称且与@Autowired类似的特殊情况下,@Resource查找主类型匹配而不是特定的命名 Bean,并解析众所周知的可解决依赖项:BeanFactoryApplicationContextResourceLoaderApplicationEventPublisherMessageSource接口。

  • 应用于字段

    @Resource
    private MovieFinder movieFinder;
    
    
  • setter 方法中注入名称为“ movieFinder”的 bean

private MovieFinder movieFinder;

    @Resource
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

10、@PostConstruct 和@PreDestroy

​ 缓存将在初始化时预先填充,并在销毁时清除(可用于项目启动完成加载缓存数据,和项目关闭是使用JVM关闭钩子关闭资源,如:zk连接等)

 @PostConstruct
    public void populateMovieCache() {
        // populates the movie cache upon initialization...
    }

    @PreDestroy
    public void clearMovieCache() {
        // clears the movie cache upon destruction...
    }

11、@Component相关注解

@Repository@Service@Controller:分别在持久层,服务层和表示层中。

12、使用 JSR 330 标准 Comments

maven依赖

<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>

12.1 使用@Inject 和@Named 进行依赖注入

代替@Autowired,可以使用@javax.inject.Inject如下:

import javax.inject.Inject;

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Inject
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    public void listMovies() {
        this.movieFinder.findMovies(...);
        ...
    }
}

@Autowired一样,可以在字段级别,方法级别和构造函数参数级别使用@Inject。此外,您可以将注入点声明为Provider,以允许按需访问范围更短的 bean,或者通过Provider.get()调用来懒惰地访问其他 bean。作为上述示例的变体:

import javax.inject.Inject;
import javax.inject.Provider;

public class SimpleMovieLister {

    private Provider<MovieFinder> movieFinder;

    @Inject
    public void setMovieFinder(Provider<MovieFinder> movieFinder) {
        this.movieFinder = movieFinder;
    }

    public void listMovies() {
        this.movieFinder.get().findMovies(...);
        ...
    }
}

如果要为应该注入的依赖项使用限定名称,则应使用@Named注解,如下所示:

import javax.inject.Inject;
import javax.inject.Named;

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Inject
    public void setMovieFinder(@Named("main") MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...
}

@Autowired一样,@Inject也可以与java.util.Optional@Nullable一起使用。这在这里更加适用,因为@Inject没有required属性。

public class SimpleMovieLister {

    @Inject
    public void setMovieFinder(Optional<MovieFinder> movieFinder) {
        ...
    }
}
public class SimpleMovieLister {

    @Inject
    public void setMovieFinder(@Nullable MovieFinder movieFinder) {
        ...
    }
}

12.2 @Named 和@ManagedBean:@ComponentComments 的标准等效项

代替@Component,可以按以下方式使用@javax.inject.Namedjavax.annotation.ManagedBean

import javax.inject.Inject;
import javax.inject.Named;

@Named("movieListener")  // @ManagedBean("movieListener") could be used as well
public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Inject
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...
}

在不指定组件名称的情况下使用@Component是很常见的。 @Named可以类似的方式使用:

import javax.inject.Inject;
import javax.inject.Named;

@Named
public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Inject
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...
}

使用@Named@ManagedBean时,可以使用与使用 SpringComments 完全相同的方式来使用组件扫描:

@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {
    ...
}

@Component相反,JSR-330 @Named和 JSR-250 ManagedBeanComments 是不可组合的。请使用 Spring 的构造型模型来构建自定义组件 Comments。

12.3 JSR-330 标准 Comments 的局限性

使用标准 Comments 时,重要的是要知道某些重要功能不可用,如下表所示:

表 7.6. Spring 组件模型元素与 JSR-330 变体

Springjavax.inject.*javax.inject 限制/Comments
@Autowired@Inject@Inject没有“必需”属性;可以与 Java 8 的Optional一起使用。
@Component@Named/@ManagedBeanJSR-330 没有提供可组合的模型,只是一种识别命名组件的方法。
@Scope(“singleton”)@SingletonJSR-330 的默认范围类似于 Spring 的prototype。但是,为了使其与 Spring 的常规默认设置保持一致,默认情况下,在 Spring 容器中声明的 JSR-330 bean 为singleton。为了使用singleton以外的范围,您应该使用 Spring 的@Scope注解。 javax.inject还提供@ScopeComments。但是,此仅用于创建自己的 Comments。
@Qualifier@ Qualifier/@ Namedjavax.inject.Qualifier只是用于构建自定义限定符的元 Comments。可以通过javax.inject.Named来关联具体的字符串限定符(例如带有值的 Spring 的@Qualifier)。
@Value-no equivalent
@Required-no equivalent
@Lazy-no equivalent
ObjectFactoryProviderjavax.inject.Provider是 Spring 的ObjectFactory的直接替代方法,只是方法名get()较短。它也可以与 Spring 的@Autowired或未 Comments 的构造函数和 setter 方法结合使用。

13、Spring 类型转换

Spring 3 引入了core.convert软件包,该软件包提供了常规的类型转换系统。系统定义了一个用于实现类型转换逻辑的 SPI,以及一个用于在运行时执行类型转换的 API。在 Spring 容器中,此系统可以用作 PropertyEditor 的替代方案,以将外部化的 bean 属性值字符串转换为所需的属性类型。公共 API 也可以在应用程序中需要类型转换的任何地方使用。

13.1 转换器 SPI

实现类型转换逻辑的 SPI 很简单且类型很严格:

package org.springframework.core.convert.converter;

public interface Converter<S, T> {

    T convert(S source);
}

要创建自己的转换器,只需实现上面的接口。将S设置为要转换的类型,并将T设置为要转换的类型。如果需要将S的集合或数组转换为T的数组或集合,则也可以透明地应用此类转换器,前提是还已委派了委派的数组/集合转换器(默认情况下DefaultConversionService这样做)。

对于每次对convert(S)的调用,保证源参数不为 null。如果转换失败,您的 Converter 可能会抛出任何未经检查的异常;具体来说,应抛出IllegalArgumentException以报告无效的源值。注意确保Converter实现是线程安全的。

为方便起见,在core.convert.support包中提供了几种转换器实现。这些包括从字符串到数字和其他常见类型的转换器。以StringToInteger为例,说明典型的Converter实现:

package org.springframework.core.convert.support;

final class StringToInteger implements Converter<String, Integer> {

    public Integer convert(String source) {
        return Integer.valueOf(source);
    }

13.2 ConverterFactory

当您需要集中整个类层次结构的转换逻辑时,例如,当从 String 转换为 java.lang.Enum 对象时,请实现ConverterFactory

package org.springframework.core.convert.converter;

public interface ConverterFactory<S, R> {

    <T extends R> Converter<S, T> getConverter(Class<T> targetType);
}

参数化 S 为您要转换的类型,参数化 R 为定义可以转换为的类的“范围”的基本类型。然后实现 getConverter(Class),其中 T 是 R 的子类。

StringToEnum ConverterFactory 为例:

package org.springframework.core.convert.support;

final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {

    public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
        return new StringToEnumConverter(targetType);
    }

    private final class StringToEnumConverter<T extends Enum> implements Converter<String, T> {

        private Class<T> enumType;

        public StringToEnumConverter(Class<T> enumType) {
            this.enumType = enumType;
        }

        public T convert(String source) {
            return (T) Enum.valueOf(this.enumType, source.trim());
        }
    }
}

14、配置全局日期和时间格式

默认情况下,未使用@DateTimeFormatComments 的日期和时间字段是使用DateFormat.SHORT样式从字符串转换的。如果愿意,可以通过定义自己的全局格式来更改此设置。

您将需要确保 Spring 不注册默认格式器,而应该手动注册所有格式器。根据使用的是 Joda-Time 库,使用org.springframework.format.datetime.joda.JodaTimeFormatterRegistrarorg.springframework.format.datetime.DateFormatterRegistrar类。

例如,以下 Java 配置将注册全局’`yyyyMMdd’格式。此示例不依赖于 Joda-Time 库:

@Configuration
public class AppConfig {

    @Bean
    public FormattingConversionService conversionService() {

        // Use the DefaultFormattingConversionService but do not register defaults
        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false);

        // Ensure @NumberFormat is still supported
        conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());

        // Register date conversion with a specific global format
        DateFormatterRegistrar registrar = new DateFormatterRegistrar();
        registrar.setFormatter(new DateFormatter("yyyyMMdd"));
        registrar.registerFormatters(conversionService);

        return conversionService;
    }
}

15、应用程序属性文件

SpringApplication将从以下位置的application.properties文件中加载属性,并将它们添加到 Spring Environment中:

  • 当前目录的/config子目录。
  • 当前目录
  • Classpath/config
  • Classpath 根

该列表按优先级排序(在列表较高位置定义的属性会覆盖在较低位置定义的属性)。

16、CORS 支持(跨域请求)

解决方案:

  • 可以通过使用自定义的addCorsMappings(CorsRegistry)方法注册WebMvcConfigurer bean 来定义全局 CORS 配置:
@Configuration
public class MyConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                 registry.addMapping("/**")
       			.allowedOrigins("http://localhost:8081")
        		.allowedMethods("*")
        		.allowedHeaders("*");
            }
        };
    }
}
	/** 表示本应用的所有方法都会去处理跨域请求, allowedMethods 表示允许通过的请求数,allowedHeaders 则表示允许的请求头。经过这样的配置之后,就不必在每个方法上单独配置跨域了。
	
存在的问题
	了解了整个 CORS 的工作过程之后,我们通过 Ajax 发送跨域请求,虽然用户体验提高了,但是也有潜在的威胁存在,常见的就是 CSRF(Cross-site request forgery)跨站请求伪造。跨站请求伪造也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF ,是一种挟制用户在当前已登录的 Web 应用程序上执行非本意的操作的攻击方法
	于此,浏览器在实际操作中,会对请求进行分类,分为简单请求,预先请求,带凭证的请求等,预先请求会首先发送一个 options 探测请求,和浏览器进行协商是否接受请求。默认情况下跨域请求是不需要凭证的,但是服务端可以配置要求客户端提供凭证,这样就可以有效避免 csrf 攻击。
  • 添加 Filter 的方式,配置 CORS 规则,并手动指定对哪些接口有效
/**
     * 配置跨域访问的过滤器
     * @return
     */
    @Bean
    public FilterRegistrationBean registerFilter(){
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.addUrlPatterns("/*");
        bean.setFilter(new CrosFilter());
        return bean;
    }
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
 
public class CrosFilter implements javax.servlet.Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
 
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) servletResponse;
        //*号表示对所有请求都允许跨域访问
        res.addHeader("Access-Control-Allow-Origin", "*");
        res.addHeader("Access-Control-Allow-Methods", "*");
        filterChain.doFilter(servletRequest, servletResponse);
    }
 
    @Override
    public void destroy() {
 
    }
}
  • 使用@CrossOrigin 注解实现
//类或方法上添加注解
@CrossOrigin(origins = {"http://localhost:9000", "null"})
  • 通过Nginx配置转发解决跨域
server {
     listen       80;
     server_name  xxx.com;
     #charset koi8-r;
     #access_log  logs/host.access.log  main;

     location /client { #访问客户端路径
         proxy_pass http://localhost:81;
         proxy_redirect default;
     }
     location /apis { #访问服务器路径
         rewrite  ^/apis/(.*)$ /$1 break;
         proxy_pass   http://localhost:82;
    }
}

17、配置 SSL

以通过设置各种server.ssl.*属性(通常在application.propertiesapplication.yml中)来声明性地配置 SSL。例如:

server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=another-secret

18、使用 Jetty 代替 Tomcat

Maven 中的示例:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

19、启用 HTTP 响应压缩

Jetty,Tomcat 和 Undertow 支持 HTTP 响应压缩。可以通过application.properties启用它:

server.compression.enabled=true

默认情况下,响应的长度必须至少为 2048 个字节才能执行压缩。可以使用server.compression.min-response-size属性进行配置。

默认情况下,仅当响应的 Content Type 为以下之一时,才会压缩它们:

  • text/html
  • text/xml
  • text/plain
  • text/css

可以使用server.compression.mime-types属性进行配置。

20、项目启动时初始化资源

  • 实现CommandLineRunner接口(多个使用@Order注解来实现资源加载的先后顺序,值越小,优先级越高)
  • 实现ApplicationRunner接口(多个使用@Order注解来实现资源加载的先后顺序,值越小,优先级越高)
  • 使用注解@PostConstruct

@PostConstruct使用特点如下:

  • 只有一个非静态方法能使用此注解
  • 被注解的方法不得有任何参数
  • 被注解的方法返回值必须为void
  • 被注解方法不得抛出已检查异常
  • 此方法只会被执行一次

21、session 共享

项目中添加maven依赖:Spring Session 以及 Redis,如下:

	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

配置文件中配置redis即可

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值