概述
BeanFactory和FactoryBean
BeanFactory是一个接口:
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
解释:
- 容器接口:Spring IoC容器的根接口,提供配置框架和基本功能。用于管理Spring Beans的生命周期
- 延迟加载:默认情况下,BeanFactory实现类(如DefaultListableBeanFactory)采用延迟加载策略,只有在第一次访问某个bean时,才会实例化这个bean
- 依赖查找:提供getBean方法可根据bean的名字或类型从容器中查找bean
FactoryBean是一个泛型接口:
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
// 用来实现动态构建Bean
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
解释:
- 自定义Bean实例化逻辑:FactoryBean接口允许用户自定义创建Bean的逻辑。通过实现FactoryBean接口,可以定制复杂的Bean创建过程
- 代理对象创建:常用于创建代理对象,如AOP代理、动态代理等。Spring的AOP功能依赖于FactoryBean
- 抽象Bean:可以创建抽象的或多变的Bean实例,而不需要直接在配置文件中定义具体的Bean类型
Spring Cloud OpenFeign组件,客户端的代理类,就是使用FactoryBean来实现的。
区别:
- 功能不同:
BeanFactory:作为IoC容器的根接口,用于管理Spring beans的生命周期和依赖注入。
FactoryBean:用于自定义bean的创建逻辑,允许用户实现复杂的bean实例化过程。 - 使用场景:
BeanFactory:用于加载和管理Spring应用中的所有bean。
FactoryBean:用于创建复杂bean或代理bean,通常在需要自定义bean实例化过程时使用。 - 实现方式:
BeanFactory:通过Spring框架提供的实现类(如DefaultListableBeanFactory)来实现。
FactoryBean:通过用户实现FactoryBean接口来实现。
classpath
和classpath*
区别:
classpath
:只会到你指定的class路径中查找文件;classpath*
:不仅包含class路径,还包括jar文件中进行查找。
Ant风格
Ant通配符有三种:
通配符 | 说明 |
---|---|
? | 匹配任何单字符 |
* | 匹配0或任意数量的字符 |
** | 匹配0或更多的目录 |
举例:
URL路径 | 说明 |
---|---|
/project/*.a | 可匹配项目根路径下在project路径下的所有.a 文件 |
/project/p?ttern | 可匹配项目根路径下/project/pattern 和/project/pXttern 等 |
/**/example | 可匹配项目根路径下/project/example ,/project/foow/example 和/example |
/**/*.jsp | 可匹配项目根路径下所有.jsp 文件 |
最长匹配原则(has more characters)
现有URL请求/app/dir/file.jsp
,假设存在两个路径匹配模式/**/*.jsp
和/app/dir/*.jsp
,那么会根据模式/app/dir/*.jsp
来匹配。
@ResponseBody和@RequestBody
@RequestBody用于Controller中方法参数,读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,完成数据绑定;
使用时机:
A) GET、POST方法, 根据request header Content-Type的值来判断:
- application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据@RequestParam, @ModelAttribute也可以处理,当然@RequestBody也能处理);
- multipart/form-data, 不能处理(即使用@RequestBody不能处理这种格式的数据);
- 其他格式, 必须(其他格式包括application/json, application/xml等。这些格式的数据,必须使用@RequestBody来处理);
B) PUT方法, 根据request header Content-Type的值来判断:
- application/x-www-form-urlencoded, 必须;
- multipart/form-data, 不能处理;
- 其他格式, 必须;
说明:request的body部分的数据编码格式由header部分的Content-Type指定;
@ResponseBody
用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。通常用来返回JSON或XML数据,在使用此注解之后不会再试图走处理器,而是直接将数据写入到输入流中,效果等同于通过response对象输出指定格式的数据。
使用时机:
返回数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;
区别
- Responsebody 注解表示该方法的返回的结果直接写入 HTTP 响应正文(ResponseBody)中,一般在异步获取数据时使用;
- 在使用 @RequestMapping 后,返回值通常解析为跳转路径,加上 @Responsebody 后返回结果不会被解析为跳转路径,而是直接写入HTTP 响应正文中。例如,异步获取 json 数据,加上 @Responsebody 注解后,就会直接返回 json 数据。
- @RequestBody 注解则是将 HTTP 请求正文插入方法中,使用适合的 HttpMessageConverter 将请求体写入某个对象。
例子:
@RequestMapping(value = "person/login")
@ResponseBody
// 将请求中的datas写入Person对象中
public Person login(@RequestBody Person person) {
// 不会被解析为跳转路径,而是直接写入HTTP响应正文中
return person;
}
@RequestParam,@PathVariable
@RequestMapping(value = "/user/{uid}", method = RequestMethod.GET)
public void get(@RequestParam(value = "nickname", required = false, defaultValue = "johnny" ) String name, @PathVariable String uid) {
}
以URLhttp://localhost:8080/user/1234435?nickname=johnny
为例:
@RequestParam是?
后面的URL的一部分,支持三种参数:
- defaultValue:如果本次请求没有携带这个参数,或参数为空,就会启用默认值;
- required:表示是不是必须的,默认true;
- value:K-V键值对里的K。
@PathVariable是?
前面的URL的一部分。
接口方法定义时,@RequestParam 后面的变量定义 可以和前面的 value 里面的定义不相同,但是"?"后面的 key-value 键值对必须是 value 定义的键。但是@PathVariable 后面的变量定义必须和接口的 URL 里面的,即@RequestMapping 里面 value 定义的大括号 {} 相同。
两者的作用都是将request里的参数的值绑定到contorl里的方法参数里的,这两个在 web 开发,即接口开发中,使用最多,都是 spring 框架里面的注解。
@PathParam
这个注解是和spring的pathVariable是一样的,也是基于模板的,jboss包下面的一个实现。
@QueryParam 是 JAX-RS 本来就提供的,和Spring的RequestParam作用一致
SpringMVC @Response返回String中文乱码
项目开发中如果没有遇到乱码,那你可能不是一个真正的开发;遇到乱码,总是习惯性去网上乱搜一气,实际上乱码的根源会有很多种情况,现象也不一样。这方面,目前菜逼的我也是乱搜一气,先排除一些不靠谱的解决方案,然后去尝试那些有理有据,适合自己项目情况的解决方案,假如成功,就了事,也没有时间和激情去追本溯源(需要改正),不行就换一种解决方法;
另,关于乱码,建议多度几遍《深入分析Java Web技术内幕》书籍的第三章:深入分析Java Web中的中文编码问题。
现在遇到的一种情况是,spring web响应乱码。一种可行的解决方法:
在springMVC的配置文件中(springMVC-xx.xml),修改<mvc:annotation-driven/>
为:
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
乱码原因:org.springframework.http.converter.StringHttpMessageConverter有个final修饰的Charset DEFAULT_CHARSET=Charset.forName(“ISO-8859-1”)常量。即当返回类型为String时,返回类型为text/plain,字符被设置为默认字符ISO-8859-1。
@Required注解检查依赖
依赖检查,该注解只能用在set方法上,并通过xml文件的property属性注入。一旦用了这个注解,那么容器在初始化bean的时候必须要进行set,也就是说必须对这个值进行依赖注入。
@Primary & @Qualifier
@Qualifier
This annotation may be used on a field or parameter as a qualifier for candidate beans when autowiring. It may also be used to annotate other custom annotations that can then in turn be used as qualifiers.
这个注释可用于作为预备bean的字段或参数,也可以用在其他的自定义注释下;@Qualifier(“XXX”),Spring的Bean注入配置注解,该注解指定注入的Bean的名称,Spring框架使用byName方式寻找合格的bean,这样就消除byType方式产生的歧义。
@Primary
Indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency. If exactly one ‘primary’ bean exists among the candidates, it will be the autowired value. This annotation is semantically equivalent to the element’s primary attribute
配置文件
基于Java类定义Bean配置元数据中的@Configuration注解的类等价于XML配置文件,@Bean注解的方法等价于XML配置文件中的Bean定义。基于Java类定义Bean配置元数据需要通过AnnotationConfigApplicationContext加载配置类及初始化容器,类似于XML配置文件需要使用ClassPathXmlApplicationContext加载配置文件及初始化容器。
在遗留老项目里会碰到;
<context:component-scan
base-package="com"
resource-pattern="**/*.class"
name-generator="org.springframework.context.annotation.AnnotationBeanNameGenerator"
use-default-filters="true"
annotation-config="true">
<context:include-filter type="aspectj" expression="*"/>
<context:exclude-filter type="regex" expression="aa"/>
</context:component-scan>
默认情况下将自动扫描@Component、@ManagedBean、@Named注解的类并将其注册为Spring管理Bean。@Aspect注解不能被Spring自动识别并注册为Bean。
base-package
:表示扫描注解类的开始位置,即将在指定的包中扫描,其他包中的注解类将不被扫描,默认将扫描所有类路径;resource-pattern
:表示扫描注解类的后缀匹配模式,即 “base-package+resource-pattern” 将组成匹配模式用于匹配类路径中的组件,默认后缀为"**/*.class"
,即指定包下的所有以.class
结尾的类文件;name-generator
:Bean标识符默认生成策略,对应AnnotationBeanNameGenerator,其将生成以小写开头的类名(不包括包名);可以自定义自己的标识符生成策略;use-default-filters
:默认为true表示扫描@Component、@ManagedBean、@Named注解类,改为false默认将不扫描这些注解定义的Bean,即这些注解类不能被扫描到,即不能通过这些注解进行Bean定义;annotation-config
:表示是否自动支持注解实现Bean依赖注入,默认支持;设置为false,将关闭支持注解的依赖注入;- exclude-filter:比include-filter具有更高优先级;
- type:过滤器类型,目前支持注解类型、类类型、正则表达式、aspectj表达式过滤器,自定义过滤器实现
org.springframework.core.type.filter.TypeFilter
即可; - expression:过滤器表达式。
<aop:aspectj-autoproxy proxy-target-class="true"/>
用于开启Spring对@AspectJ风格切面的支持。
default-lazy-init="true">
: