文档章节

spring annotation

zswitos
 zswitos
发布于 2015/04/21 22:20
字数 3409
阅读 261
收藏 8
点赞 0
评论 0

Spring1

1、spring的IOC container(1)

    org.springframework.beans  org.springframework.context构成了springIoc的容器核心框架

1.1FactoryBean 这个接口是spring的创建类的所需要实现的接口

创建一个类

T getObject() throws Exception;

返回创建类的class

Class<?> getObjectType();

判断创建类是否为单例

boolean isSingleton();

1.2 BeanFactory 这个接口是spring对外提供可以配置的管理机制,管理任何类型的对象

//工厂对象的前缀
String FACTORY_BEAN_PREFIX = "&";


//根据名字获取的对象instance
Object getBean(String name) throws BeansException;


//根据名字和类型获取对象instance
<T> T getBean(String name, Class<T> requiredType) throws BeansException;

/根据类型获取一个类instance
<T> T getBean(Class<T> requiredType) throws BeansException;

//根据名字和构造器的参数(或者工厂方法的参数)返回一个类instance

Object getBean(String name, Object... args) throws BeansException;


//根据类型和和构造器的参数(或者工厂方法的参数)返回一个类instance
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;



//根据名字(bean definition name)判断是否含有一个类instance
boolean containsBean(String name);


判断是否为单例
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

//判断是为原型

boolean isPrototype(String name) throws NoSuchBeanDefinitionException;


//根据类的定义名称判断是否是一个指定的类型
boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;

//根据定义名称返回一个类的Class对象

Class<?> getType(String name) throws NoSuchBeanDefinitionException;

//根据一个定义名字返回这个类的所有别名组成的数组
String[] getAliases(String name);

    

如下图是它的一个核心子类ApplicationContext

The interface org.springframework.context.ApplicationContext represents the Spring IoC
container and is responsible for instantiating, configuring, and assembling the aforementioned beans.

它是代表了spring ioc容器 初始化 配置 装载 它管理的bean

一个spring管理类的元数据定义有XML文件和注解两种方法,其中注解有分为Annotation-based configuration(spring自带的注解)和Java-based configuration(jdk自带注解@Configuration, @Bean, @Import and @DependsOn annotations)

.

XML配置

可以支持导入,以便按照实际需求拆分定义bean,如下:

<beans>
    <import resource="services.xml"/>
    <import resource="resources/messageSource.xml"/>
    <import resource="/resources/themeSource.xml"/>
    <bean id="bean1" class="..."/>
    <bean id="bean2" class="..."/>
</beans>


ApplicationContext 可以返回想要的bean

The ApplicationContext enables you to read bean definitions and access them as follows:
// create and configure beans
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);
// use configured instance
List<String> userList = service.getUsernameList();

不提倡在系统中这样应用的获取bean,它高度耦合了Spring的代码

ApplicationContext context =new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});

 应使用依赖注入的办法实现松耦合

(实质上的xml 或者注解配置的信息是元数据,它并不是spring真正使用的类)

Within the container itself, these bean definitions are represented as BeanDefinition objects, which
contain (among other information) the following metadata:


XML配置:
The idref element
一、
<bean id="theTargetBean" class="..."/>
<bean id="theClientBean" class="...">
<property name="targetName">
<idref bean="theTargetBean" />
</property>
</bean>
二、
<bean id="theTargetBean" class="..." />
<bean id="client" class="...">
<property name="targetName" value="theTargetBean" />
</bean>

两种方法区别:
    idref在部署的时候spring ioc容器要对idref的类去验证,看是否存在
    property在部署的时候容器不会自动检测是否存在

spring的scope

Scope Description
singleton (Default) Scopes a single bean definition to a
single object instance per Spring IoC container.
prototype Scopes a single bean definition to any number of
object instances.
request Scopes a single bean definition to the lifecycle
of a single HTTP request; that is, each HTTP
request has its own instance of a bean created
off the back of a single bean definition. Only
Spring Framework
57Spring Framework Reference Documentation
Scope
Description
valid in the context of a web-aware Spring
ApplicationContext.
session Scopes a single bean definition to the lifecycle of
an HTTP Session. Only valid in the context of a
web-aware Spring ApplicationContext.
global session Scopes a single bean definition to the lifecycle
of a global HTTP Session. Typically only
valid when used in a portlet context. Only
valid in the context of a web-aware Spring
ApplicationContext.
application Scopes a single bean definition to the lifecycle of
a ServletContext. Only valid in the context of
a web-aware Spring ApplicationContext.

single如下图



prototype如下图:


但是在single的scope下引用prototype的时候只是会出现问题,bean的引用关系在第一次初始化的时候就会被确定,single的属性一直不会被更新,所以prototype的对象不会被更新为最新创建的对象,解决办法如下:

public abstract class Chinese implements Person  
{  
    public Chinese()  
    {  
        System.out.pritln("Spring实例化主调bean:Chinese实例...");  
    }  
    //定义一个抽象方法,该方法将由Spring负责实现  
    publc abstract getAxe();  
    public void useAxe()  
    {  
        System.out.println("正在使用"+getAxe()+"看菜!");  
    }  
      
}  


为了让Spring知道如何实现该方法,我们需要在配置文件中使用<lookup-method.../>元素指定如下两个属性:name:指定需要让Spring实现的方法
bean:指定Spring实现该方法后的返回值。


<bean id="chinese" class="com.feng.service.impl.Chinese">  
    <!--指定getAxe方法返回steelAxe  
    每次调用getAxe方法将获取新的steelAxe对象-->  
    <look-method name="getAxe" bean="steelAxe"/>  
    -->  
</bean>  

上面的代码指定Spring将负责实现getAxe()方法,该方法的返回值是容器中的steelAxe Bean实例。
(引用自博客:http://blog.csdn.net/howlaa/article/details/8332519,感谢博主)


Request Scope

If you access scoped beans within Spring Web MVC, in effect, within a request that is processed
by the Spring DispatcherServlet, or DispatcherPortlet, then no special setup is necessary:
DispatcherServlet and DispatcherPortlet already expose all relevant state.

使用DispatcherServlet代理的类都是request scope

注意:

If you use a Servlet 2.5 web container, with requests processed outside of
Spring’s DispatcherServlet (for example, when using JSF or Struts), you need
to register the org.springframework.web.context.request.RequestContextListener
ServletRequestListener.

使用Servlet 2.5 web需要使用该RequestContextListener进行转换!


LifeCycle


                                                                                (图片摘自:http://developer.51cto.com/art/201104/255961.htm 感谢博主! )



一、spring Bean的作用域:scope=singleton(默认,单例,生成一个实例)

二、spring Bean的作用域:scope=prototype(多线程, 生成多个实例)

三、单例模式,默认在程序初始化的时候实例化(lazy-init="false")

四、prototype,getBean的时候才是实例化

五、lazy-init 只对单例模式起作用,对 prototype 不起作用(因为  prototype 默认就不是程序初始化的时候实例化的

1.容器寻找Bean的定义信息并且将其实例化。

2.受用依赖注入,Spring按照Bean定义信息配置Bean的所有属性。

3.如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。

4.如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。

5.如果BeanPostProcessor和Bean关联,那么它们的postProcessBeforeInitialzation()方法将被调用。

6.如果Bean指定了init-method方法,它将被调用。

7.最后,如果有BeanPsotProcessor和Bean关联,那么它们的postProcessAfterInitialization()方法将被调用。
到这个时候,Bean已经可以被应用系统使用了,并且将被保留在Bean Factory中知道它不再需要。

有两种方法可以把它从Bean Factory中删除掉。

1.如果Bean实现了DisposableBean接口,destory()方法被调用。

2.如果指定了订制的销毁方法,就调用这个方法。

Bean在Spring应用上下文的生命周期与在Bean工厂中的生命周期只有一点不同,
唯一不同的是,如果Bean实现了ApplicationContextAwre接口,setApplicationContext()方法被调用。

只有singleton行为的bean接受容器管理生命周期。
non-singleton行为的bean,Spring容器仅仅是new的替代,容器只负责创建。


对于singleton bean,Spring容器知道bean何时实例化结束,何时销毁,
Spring可以管理实例化结束之后,和销毁之前的行为,管理bean的生命周期行为主要未如下两个时机:
Bean全部依赖注入之后
Bean即将销毁之前

1)依赖关系注入后的行为实现:
有两种方法:A.编写init方法  B.实现InitializingBean接口
afterPropertiesSet和init同时出现,前者先于后者执行,使用init方法,需要对配置文件加入init-method属性

2)bean销毁之前的行为
有两种方法:A.编写close方法  B.实现DisposableBean接口
destroy和close同时出现,前者先于后者执行,使用close方法,需要对配置文件加入destroy-method属性

(摘自:http://blog.csdn.net/java958199586/article/details/7469147,感谢博主!)

清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责

生命周期就是springIOC容器在初始化一个bean的时候的预留一些接口,(每个时期都有有三个等级:Bean级别,BeanFactory级别:,Application级别)


自定义的Bean不到万不得已不要直接引用Spring API产生耦合,这是种下一个孽缘,会有恶果的,能用注解用注解,这才是善缘。

如果你想修改一个spring ioc 并未对外暴露的api,可以通过集成一个BeanPostProcessor来达到目的,同理可以修改BeanFactory

a BeanPostProcessor yourself. For more information, see Section 5.8, “Container Extension Points

/**
* Factory hook that allows for custom modification of new bean instances,
* e.g. checking for marker interfaces or wrapping them with proxies.
*
* <p>ApplicationContexts can autodetect BeanPostProcessor beans in their
* bean definitions and apply them to any beans subsequently created.
* Plain bean factories allow for programmatic registration of post-processors,
* applying to all beans created through this factory.
*
* <p>Typically, post-processors that populate beans via marker interfaces
* or the like will implement {@link #postProcessBeforeInitialization},
* while post-processors that wrap beans with proxies will normally
* implement {@link #postProcessAfterInitialization}.
*
* @author Juergen Hoeller
* @since 10.10.2003
* @see InstantiationAwareBeanPostProcessor
* @see DestructionAwareBeanPostProcessor
* @see ConfigurableBeanFactory#addBeanPostProcessor
* @see BeanFactoryPostProcessor
*/
public interface BeanPostProcessor {

  /**
   * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
   * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
   * or a custom init-method). The bean will already be populated with property values.
   * The returned bean instance may be a wrapper around the original.
   * @param bean the new bean instance
   * @param beanName the name of the bean
   * @return the bean instance to use, either the original or a wrapped one; if
   * {@code null}, no subsequent BeanPostProcessors will be invoked
   * @throws org.springframework.beans.BeansException in case of errors
   * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
   */
  Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

  /**
   * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
   * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
   * or a custom init-method). The bean will already be populated with property values.
   * The returned bean instance may be a wrapper around the original.
   * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
   * instance and the objects created by the FactoryBean (as of Spring 2.0). The
   * post-processor can decide whether to apply to either the FactoryBean or created
   * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
   * <p>This callback will also be invoked after a short-circuiting triggered by a
   * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
   * in contrast to all other BeanPostProcessor callbacks.
   * @param bean the new bean instance
   * @param beanName the name of the bean
   * @return the bean instance to use, either the original or a wrapped one; if
   * {@code null}, no subsequent BeanPostProcessors will be invoked
   * @throws org.springframework.beans.BeansException in case of errors
   * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
   * @see org.springframework.beans.factory.FactoryBean
   */
  Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}
/**
* Allows for custom modification of an application context's bean definitions,
* adapting the bean property values of the context's underlying bean factory.
*
* <p>Application contexts can auto-detect BeanFactoryPostProcessor beans in
* their bean definitions and apply them before any other beans get created.
*
* <p>Useful for custom config files targeted at system administrators that
* override bean properties configured in the application context.
*
* <p>See PropertyResourceConfigurer and its concrete implementations
* for out-of-the-box solutions that address such configuration needs.
*
* <p>A BeanFactoryPostProcessor may interact with and modify bean
* definitions, but never bean instances. Doing so may cause premature bean
* instantiation, violating the container and causing unintended side-effects.
* If bean instance interaction is required, consider implementing
* {@link BeanPostProcessor} instead.
*
* @author Juergen Hoeller
* @since 06.07.2003
* @see BeanPostProcessor
* @see PropertyResourceConfigurer
*/
public interface BeanFactoryPostProcessor {

  /**
   * Modify the application context's internal bean factory after its standard
   * initialization. All bean definitions will have been loaded, but no beans
   * will have been instantiated yet. This allows for overriding or adding
   * properties even to eager-initializing beans.
   * @param beanFactory the bean factory used by the application context
   * @throws org.springframework.beans.BeansException in case of errors
   */
  void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

由衷赞叹的spring设计如此之灵活,可扩展性如此之高啊,顶礼膜拜!(可以借鉴到自己的代码之中)


初始化:
public interface
InitializingBean {

  /**
   * Invoked by a BeanFactory after it has set all bean properties supplied
   * (and satisfied BeanFactoryAware and ApplicationContextAware).
   * <p>This method allows the bean instance to perform initialization only
   * possible when all bean properties have been set and to throw an
   * exception in the event of misconfiguration.
   * @throws Exception in the event of misconfiguration (such
   * as failure to set an essential property) or if initialization fails.
   */
  void afterPropertiesSet() throws Exception;

}
(@PostConstruct) 初始化的接口(注解) init-method


销毁:
public interface DisposableBean {

  /**
   * Invoked by a BeanFactory on destruction of a singleton.
   * @throws Exception in case of shutdown errors.
   * Exceptions will get logged but not rethrown to allow
   * other beans to release their resources too.
   */
  void destroy() throws Exception;

}
(@PreDestroy)销毁的接口(注解) destroy-method





给一个bean注入一个ApplicationContext
public interface
ApplicationContextAware extends Aware {

  /**
   * Set the ApplicationContext that this object runs in.
   * Normally this call will be used to initialize the object.
   * <p>Invoked after population of normal bean properties but before an init callback such
   * as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()}
   * or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader},
   * {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and
   * {@link MessageSourceAware}, if applicable.
   * @param applicationContext the ApplicationContext object to be used by this object
   * @throws ApplicationContextException in case of context initialization errors
   * @throws BeansException if thrown by application context methods
   * @see org.springframework.beans.factory.BeanInitializationException
   */
  void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}
给一个Bean注入创建他的工厂
public interface
BeanFactoryAware extends Aware {

  /**
   * Callback that supplies the owning factory to a bean instance.
   * <p>Invoked after the population of normal bean properties
   * but before an initialization callback such as
   * {@link InitializingBean#afterPropertiesSet()} or a custom init-method.
   * @param beanFactory owning BeanFactory (never {@code null}).
   * The bean can immediately call methods on the factory.
   * @throws BeansException in case of initialization errors
   * @see BeanInitializationException
   */
  void setBeanFactory(BeanFactory beanFactory) throws BeansException;

}
给一个bean注入他自己的内存注册的ID
public interface
BeanNameAware extends Aware {

  /**
   * Set the name of the bean in the bean factory that created this bean.
   * <p>Invoked after population of normal bean properties but before an
   * init callback such as {@link InitializingBean#afterPropertiesSet()}
   * or a custom init-method.
   * @param name the name of the bean in the factory.
   * Note that this name is the actual bean name used in the factory, which may
   * differ from the originally specified name: in particular for inner bean
   * names, the actual bean name might have been made unique through appending
   * "#..." suffixes. Use the {@link BeanFactoryUtils#originalBeanName(String)}
   * method to extract the original bean name (without suffix), if desired.
   */
  void setBeanName(String name);

}

这样的做法还是不好滴,因为又产生了spring的依赖,spring 2.5以后可以支持@Autowired这个注解,所以,spring一直提倡在自己代码内不要直接依赖springAPI,不然注解,不然xml配置!

<bean id="inheritedTestBeanWithoutClass" abstract="true">
<property name="name" value="parent"/>
<property name="age" value="1"/>
</bean>
<bean id="inheritsWithClass" class="org.springframework.beans.DerivedTestBean"
parent="inheritedTestBeanWithoutClass" init-method="initialize">
<property name="name" value="override"/>
<!-- age will inherit the value of 1 from the parent bean definition-->
</bean>

spring的继承配置,当父类配置为abstract="true" 仅仅能被当天的xml模板使用,不能被初始化长生实体类,也不能被当作ref去被别的类引用,会报错的被引用了

Customizing instantiation logic with a FactoryBean

如果你的类初始化需要大量工作流程,过于复杂,不用担心,Spring IOC为你准备了FactoryBean,只有实现此接口你便可以随心所欲创造你的类,不需要在xml配置那么多的元算,如此优雅配置即可:

<bean id="factoryBeanOne" class="com.study.demo.factorybean.SimpleFactoryBean" > </Bean>

© 著作权归作者所有

共有 人打赏支持
zswitos
粉丝 4
博文 58
码字总数 54950
作品 0
海淀
程序员
Spring Aop配置时的切入点表达式

对应的中文: 任意公共方法的执行: execution(public (..)) 任何一个以“set”开始的方法的执行: execution( set(..)) AccountService 接口的任意方法的执行: execution( com.xyz.service...

cswy
2013/12/05
0
0
spring vmc3.1.1 上,通过AnnotationMethodHandlerAdap...

spring vmc3.1.1 下,通过AnnotationMethodHandlerAdapter配置webBindingInitializer失效解决方案 问题: spring vmc3.1.1 下,通过AnnotationMethodHandlerAdapter配置webBindingInitializ......

爪哇小贩
2013/03/23
0
2
spring aop 切点声明

多条件 任意公共方法的执行: execution(public (..)) 任何一个以“set”开始的方法的执行: execution( set(..)) AccountService 接口的任意方法的执行: execution( com.xyz.service.Accou...

Canaan_
2017/11/05
0
0
Dao层系列-4-Hibernate Spring Annotation

之前几篇文章主要是介绍 Hibernate、Hibernate Annotation、Hibernate Spring 集成 这篇文章主要是:Hibernate和Spring集成后都使用注解的方式。 Hibernate使用注解进行关系映射,Spring使用...

onlyfish
2013/07/19
0
0
采用annotation对spring-mvc进行登录权限控制

在web系统中,判断用户是否登录是一个常用功能. 本文提出一种采用annotation对spring-mvc进行用户登录判断的方法. [程序源代码][1] 方法简介 建立一个annotation, 在需要登录判断的spring-mv...

taojinhuo
2013/01/05
0
17
spring mvc 配置失效了?

版本:spring 3.0以上 项目中有两个spring的配置xml,如下 项目中的web.xml web.xml的配置如下: 1、ContextLoaderListener加载applicationContext-service-database.xml 2、DispatcherServl...

听柳
05/31
0
0
SpringMVC—标签

在Spring3.0中 在Spring3.0.5这个版本上,mvc:annotation-driven/声明是没有 defaultAnnotationHandlerMapping这个属性的,对于@ResultMapping标签的解析,是写死了必须用 "org.springframe...

李长春
2011/09/15
0
0
SpringMVC—标签

在Spring3.0中 在Spring3.0.5这个版本上,mvc:annotation-driven/声明是没有 defaultAnnotationHandlerMapping这个属性的,对于@ResultMapping标签的解析,是写死了必须用 "org.springframe...

李长春
2011/09/15
0
0
Spring 3.0.0 is Now Available (2009-12-16)

Spring 3.0.0 is Now Available News and Announcements It's here just in time for the holidays! Arjen Poutsma has just announced that Spring 3.0.0 is now final and Juergen Hoeller......

晨曦之光
2012/03/09
0
0
Spring 注解注入详解

1.@Autowired注解(不推荐使用,建议使用@Resource) @Autowired可以对成员变量、方法和构造函数进行标注,来完成自动装配的工作。@Autowired的标注位置不同,它们都会在Spring在初始化这个b...

wpb王鹏博
2015/06/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

设计神器 - 摹客设计系统上线了 | 晒出你的设计规范,赢iPad Pro!

在国内,设计规范也许还是个不太常用的概念,但是如果你正好有参与互联网公司的产品设计,你应该早就已经体会到设计规范的重要性了。UI设计师总是要花费大量的时间和精力向开发描述一大堆设计...

mo311
4分钟前
0
0
Thymeleaf 使用过程中的一些记录

Thymeleaf格式化时间: th:value="${#dates.format(gw.regDT,'yyyy-MM-ddHH:mm:ss')}" Thymeleaf select反选: <select id="status" name="status" th:field="${gw.status}" th:value="${gw.......

惊尘大人
6分钟前
0
0
istio源码分析之pilot-discovery模块分析

本文分析的istio代码版本为0.8.0,commit为0cd8d67,commit时间为2018年6月18日。 本文为Service Mesh深度学习系列之一: Service Mesh深度学习系列part1—istio源码分析之pilot-agent模块分...

xiaomin0322
12分钟前
0
0
数据库基本操作:增删改查及联表操作

所用软件:SQL Server Management Studio 首先第一步,建立一个表。在这里命名为T1。并在里面填入几条数据。如图: T1 一.查询 查询所有:select * from T1; 按条件查询:select * from T1 ...

小_橙_子
16分钟前
0
0
Crontab作业时间设置

今天,遇到这么一个题目,周一到周五的9:00-16:59之间,每隔两分钟将某个命令运行一次。给的答案是: */2 9-16 * * 1-5 /usr/sbin/somecommand dosomething 乍一看,这个答案不对,应...

大别阿郎
20分钟前
0
0
ES17-JAVA API文档管理

1.保存文档 可以通过json工具把java对象转换成json字符串进行保存,也可以通过内置的帮助类直接构建json格式 /** * 获取客户端 * * @return */public static TransportClie...

贾峰uk
21分钟前
0
0
Python代码规范和命名规范

前言 Python 学习之旅,先来看看 Python 的代码规范,让自己先有个意识,而且在往后的学习中慢慢养成习惯 一、简明概述 1、编码 如无特殊情况, 文件一律使用 UTF-8 编码 如无特殊情况, 文件头...

blackfoxya
24分钟前
0
0
联动滑动之一:NestScrollChild和NestedScrollingParent

NestScrollChild和NestedScrollingParent 吐槽一下开源中国竟然标题字数有限制 由于项目中使用了CoordinateLayout来解决联动以及实现炫酷的UI效果,那么必须就要研究一波源码了,毕竟知其然知...

JerryLin123
41分钟前
1
0
cloudera spark2.2 读写hbase

cloudera spark2.2 读写hbase 例子 host = 'bigdata-03,bigdata-05,bigdata-04'conf = { "hbase.zookeeper.quorum": host, "hbase.mapreduce.inputtable": "student1"}k......

osenlin
46分钟前
0
0
数据库规范化

转载自 一个小时学会MySQL数据库 地址:http://www.cnblogs.com/best/p/6517755.html 截取其中 1.4 部分 用于自己学习使用 感谢作者:张果 1.4、数据库规范化 经过一系列的步骤,我们现在终于...

十万猛虎下画山
47分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部