资讯专栏INFORMATION COLUMN

java学习笔记

fevin / 289人阅读

摘要:构造函数方法进行依赖注入注入的效率最高新建方法电源供电中。。。。。无参数构造函数选创建有参的构造函数有参数构造函数多参数构造函数。。。。

一、Spring基础 1.Spring简介 1.1 核心概念
序号 概念 全称 具体内容
1 IoC Inversion of Control (控制反转) 对象创建和对象关系管理权限,由开发者转为spring
2 DI Dependency Injection(依赖注入) 对象的依赖关系的创建过程
3 AOP Aspect Oriented Programming(面向切面编程)

功能模块组成:

模块 功能 备注
Core IoC,DI 功能实现最基本实现 核心模块
Beans Bean工厂(创建对象的工厂) 核心模块
Context IoC容器,上下文 核心模块
SpEL spring 表达式语言 核心模块
JDBC JDBC封装 数据访问集成模块
ORM 数据集成框架封装,jpa jdo 数据访问集成模块
OXM 实现对象和xml转换 数据访问集成模块
JMS 生产消费实现 数据访问集成模块
Transactions 事务管理 数据访问集成模块
web web监听,初始化ioc容器,上传等 web模块
webSocket webSocket开发 web模块
Servlet spring MVC web模块
Portlet 内容集成 聚合 web模块
AOP AOP相关
Aspects Aspects面向切面编程
Instrumentation 设备相关
Messaging 消息相关
Test 测试模块

spring 包含spring MVC

1.2 相关参数解析
名称 用途 备注 类型
private 声明成员变量
有参的构造函数 关联成员变量和无参构造函数的关系
public void play() 构造一个方法play,执行具体逻辑
@Autowired 自动满足bean之间的依赖 自动装配,自动注入注解 定义组件
@Transactional @Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。 但是 Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。另外, @Transactional 注解应该只被应用到 public 方法上 事务管理
@Component 表示这个累需要在应用程序中被创建,被扫描 被spring上下文发现,自动发现注解 定义组件
@ComponentScanTransactional 自动发现应用程序中创建的类 自动扫描Component类 定义配置
@Configuration 表示当前类是一个配置类 标注类为配置类 定义配置
@Test 表示当前类是一个测试类
@RunWith(SpringJUnit4ClassRunner.class) 引入Spring单元测试模块 声明使用SpringJUnit4ClassRunner.class 测试单元 spring测试环境
@ContextConfiguration(classes = AppConfig.class) 加载配置类 spring测试环境
@Primary 首选bean 设置实现类的首选 自动装配歧义性
@Qualifier 给bean做注解 调用的时候可以通过注解区分实现类 自动装配歧义性
@Resource @Resource 相当于@Autowired + @Qualifier("userServiceNormal") java标准 自动装配歧义性
@Repository 标注数据dao实现类 本质和@Component没有区别,只是更加明确 分层架构中定义组件
@Service 标注Service实现类 本质和@Component没有区别,只是更加明确 分层架构中定义组件
@Controller 标注web、controller实现类, API接口 本质和@Component没有区别,只是更加明确 分层架构中定义组件
@Bean 当前配置类为默认配置类,自动调用
@Override 重写,重载 自雷重写父类的方法
@RequestMapping 是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。 配置url映射
@RestController 是@ResponseBody和@Controller的组合注解
Extends-继承类 全盘继承 在类的声明中,通过关键字extends来创建一个类的子类。 对于class而言,Extends用于(单)继承一个类(class)
implements-实现接口 给这个类附加额外的功能 实现接口就是在接口中定义了方法,这个方法要你自己去实现,接口可以看作一个标准,比如定义了一个动物的接口,它里面有吃(eat())这个方法,你就可以实现这个方法implements,这个方法是自己写,可以是吃苹果,吃梨子,香蕉,或者其他的。implements就是具体实现这个接口 implements用于实现一个接口(interface)
DAO DAO是传统MVC中Model的关键角色,全称是Data Access Object。DAO直接负责数据库的存取工作,乍一看两者非常类似,但从架构设计上讲两者有着本质的区别: DAO则没有摆脱数据的影子,仍然停留在数据操作的层面上,DAO则是相对数据库而言
Repository Repository蕴含着真正的OO概念,即一个数据仓库角色,负责所有对象的持久化管理。 Repository是相对对象而言, https://segmentfault.com/a/11...

接口:

接口一般是只有方法声明没有定义的。

接口可以比作协议,比如我说一个协议是“杀人”那么这个接口你可以用 砍刀去实现,至于怎么杀砍刀可以去实现,当然你也可以用抢来实现杀人接口,但是你不能用杀人接口去杀人,因为杀人接口只不过是个功能说明,是个协议,具体怎么干,还要看他的实现类。那么一个包里面如果有接口,你可以不实现。这个不影响你使用其他类。

1.3 for 循环

this.tracks.for + Enter 可以快速得到for循环

        for (String track : this.tracks) {
            System.out.println("音乐:" + track);
        }
2.Component对象

2.1 创建maven项目

2.2 创建基础目录

2.3 配置pom.xml



    4.0.0

    com.xfedu
    spring01
    1.0-SNAPSHOT

    
        
            org.springframework
            spring-context
            4.3.13.RELEASE
        

    

2.4 编写纯java版本代码

编写MessagesService

package hello;


public class MessagesService {

    /**
     * 执行打印功能
     * @return返回要打印的字符串
     */
    public String getMessage(){

        return "hello world!";
    }
}

编写MessagePrinter

package hello;

public class MessagePrinter {

    /**
     * private 建立MessagePrinter 和 MessagesService 关联关系
     */
    private MessagesService service;

    /**
     * service setter 方法 选择service 按住alt+insert 选择setter
     * 设置service的值
     * @param service
     */
    public void setService(MessagesService service) {
        this.service = service;
    }

    public void  printMessage(){

        System.out.println(this.service.getMessage());
    }
}

编写Application

package hello;


/**
 * 创建Application来调用MessagePrinter类
 */
public class Application {

    public static void main(String[] args) {

        System.out.println("application");

        //创建打印机对象
        MessagePrinter printer = new MessagePrinter();
        //创建消息服务对象
        MessagesService service = new MessagesService();
        //设置打印机的service属性
        printer.setService(service);

        //打印消息
        printer.printMessage();

    }
}

2.5 编写spring 框架版本代码

编写MessagesService

package hello;

import org.springframework.stereotype.Component;

/**
 * @Component通知spring容器,
 * 应用程序的对象(MessagesService)未来会通过spring容器自动创建出来
 * 不需要程序员通过new关键字来创建
 */
@Component
public class MessagesService {

    /**
     * ctrl+o 创建无参构造的方法(object)
     *
     */
    public MessagesService() {
        super();
        System.out.println("MessageServer....");
    }

    /**
     * 执行打印功能
     * @return返回要打印的字符串
     */
    public String getMessage(){

        return "hello world!";
    }
}

编写MessagePrinter

package hello;

import org.springframework.stereotype.Component;

/**
 * @Component通知spring容器,
 * 应用程序的对象(MessagePrinter)未来会通过spring容器自动创建出来
 * 不需要程序员通过new关键字来创建
 */
@Component
public class MessagePrinter {

    /**
     * ctrl+o 创建无参构造的方法(object)
     *
     */
    public MessagePrinter() {
        super();
        System.out.println("MessagePrinter");

    }

    /**
     * private 建立MessagePrinter 和 MessagesService 关联关系
     */
    private MessagesService service;

    /**
     * service setter 方法 选择service 按住alt+insert 选择setter
     * 设置service的值
     * @param service
     */
    public void setService(MessagesService service) {
        this.service = service;
    }

    public void  printMessage(){

        System.out.println(this.service.getMessage());
    }
}

编写ApplicationSpring

package hello;


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

/**
 * 创建Application来调用MessagePrinter类
 * @ComponentScan 扫描@Component注解的类
 */
@ComponentScan
public class ApplicationSpring {

    public static void main(String[] args) {



        System.out.println("application");
//
//        //创建打印机对象
//        MessagePrinter printer = new MessagePrinter();
//        //创建消息服务对象
//        MessagesService service = new MessagesService();
//        //设置打印机的service属性
//        printer.setService(service);
//
//        //打印消息
//        printer.printMessage();

        //初始化Spring容器
        ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationSpring.class);

    }
}

优点:通过 * @ComponentScan 扫描@Component注解的类,创建对象的时候就可以不用重新new

3.对象装配注入Bean 3.1 Bena装配(注入)的三种方式 3.1.1 隐式的bean发现机制和自动装配(主流)
1 简单案列
package hello;

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

/**
 * 创建Application来调用MessagePrinter类
 * @ComponentScan 扫描@Component注解的类
 */
@ComponentScan
public class ApplicationSpring {

    public static void main(String[] args) {



        System.out.println("application");
//
//        //创建打印机对象
//        MessagePrinter printer = new MessagePrinter();
//        //创建消息服务对象
//        MessagesService service = new MessagesService();
//        //设置打印机的service属性
//        printer.setService(service);
//
//        //打印消息
//        printer.printMessage();

        //初始化Spring容器
        ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationSpring.class);

        //从容器中获取MessagePrinter对象
        MessagePrinter printer = context.getBean(MessagePrinter.class);
        //从容器中获取MessagesService对象
        MessagesService service = context.getBean(MessagesService.class);

        System.out.println(printer);
        System.out.println(service);

        //设置打印机的service属性,printer和service 建立关联关系
        printer.setService(service);
        //打印消息调用printMessage打印
        printer.printMessage();
    }
}

从Context中获取class

ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationSpring.class);

如何在对象中获取对象

//从容器中获取MessagePrinter对象,使用context.getBean方法
MessagePrinter printer = context.getBean(MessagePrinter.class);

如何建立对象的关联关系

//设置打印机的service属性,printer和service 建立关联关系
printer.setService(service);
2. 完整的案列

1.定义CompactDisc类,

内置CompactDisc无参构造函数

paly方法

用@Component包装

2.定义CDPlayer

内置CDPlayer无参数构造函数

声明CompactDisc

构建有参构造函数关联CDPlayer和CompactDisc,利用@Autowired进行关联自动管理

定义play方法

3.定义执行main函数

先通过AnnotationConfigApplicationContext 查出类

执行paly方法

利用@ComponentScan包装,进行自动组件扫描

4.解耦组件扫描和主类

将注解和主类解耦,多带带新建配置类AppConfig

CompactDisc

package soundsystem;

import org.springframework.stereotype.Component;

@Component
public class CompactDisc {

    public CompactDisc() {
        super();
        System.out.println("CompactDisc无参构造函数");
    }

    public void play(){

        System.out.println("正在播放音乐......");
    }
}

CDPlayer

package soundsystem;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * Component 让他能被spring上下文发现
 */

@Component
public class CDPlayer {

    /**
     *private 成员变量
     */
    private CompactDisc cd;

    public CDPlayer() {
        super();
        System.out.println("CDPlayer无参数构造函数");
    }

    /**
     * Ctrl + Insert 选(Constructor)创建有参的构造函数
     * @param
     */

    @Autowired
    public CDPlayer(CompactDisc cd) {
        this.cd = cd;
        System.out.println("CDPlayer有参数构造函数");
    }

    /**
     * 定义一个方法play,执行cd.play()播放工作
     */
    public void play(){
        cd.play();

    }
}

App

package soundsystem;

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

@ComponentScan
public class App {

    public static void main(String[] args) {
         ApplicationContext context = new AnnotationConfigApplicationContext(App.class);
        CDPlayer player = context.getBean(CDPlayer.class);

        player.play();
    }
}

将注解和主类解耦,多带带新建配置类AppConfig

AppConfig

这里就配置类扫描@ComponentScan 和@Configuration 注解

package soundsystem;


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


/**
 * 这就是一个配置类
 */

@Configuration
@ComponentScan
public class AppConfig {
    public AppConfig() {
        super();
        System.out.println("配置类,用于将注解和主类解耦");
    }
}

App

这里就将@ComponentScan注解取消了

package soundsystem;


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


public class App {

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        CDPlayer player = context.getBean(CDPlayer.class);

        player.play();
    }

}
3.1.2 在XML进行显示

applicationContext.xml




    
    
    
        
        
    

MessagePrinter

package hello;

/**
 * @Component通知spring容器,
 * 应用程序的对象(MessagePrinter)未来会通过spring容器自动创建出来
 * 不需要程序员通过new关键字来创建
 */

public class MessagePrinter {

    /**
     * ctrl+o 创建无参构造的方法(object)
     *
     */
    public MessagePrinter() {
        super();
        System.out.println("MessagePrinter");

    }

    /**
     * private 建立MessagePrinter 和 MessagesService 关联关系
     */
    private MessagesService service;

    /**
     * service setter 方法 选择service 按住alt+insert 选择setter
     * 设置service的值
     * @param service
     */
    public void setService(MessagesService service) {
        this.service = service;
    }

    public void  printMessage(){
        System.out.println(this.service.getMessage());
    }
}

MessagesService

package hello;

/**
 * @Component通知spring容器,
 * 应用程序的对象(MessagesService)未来会通过spring容器自动创建出来
 * 不需要程序员通过new关键字来创建
 */

public class MessagesService {

    /**
     * ctrl+o 创建无参构造的方法(object)
     *
     */
    public MessagesService() {
        super();
        System.out.println("MessageServer....");
    }

    /**
     * 执行打印功能
     * @return返回要打印的字符串
     */
    public String getMessage(){

        return "hello world!";
    }
}

ApplicationSpring

package hello;


import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 创建Application来调用MessagePrinter类
 * @ComponentScan 扫描@Component注解的类
 */

public class ApplicationSpring {

    public static void main(String[] args) {

        System.out.println("application");
        
         //初始化Spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        //从容器中获取MessagePrinter对象
        MessagePrinter printer = context.getBean(MessagePrinter.class);

        //打印消息调用printMessage打印
        printer.printMessage();
    }
}

声明使用xml文件

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

3.1.3 在java中进行显示 3.2 Autowired 使用场景

用于管理对象之间的关联关系

3.2.1 简单的依赖注入例子

MessagePrinter

package hello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @Component通知spring容器,
 * 应用程序的对象(MessagePrinter)未来会通过spring容器自动创建出来
 * 不需要程序员通过new关键字来创建
 */
@Component
public class MessagePrinter {

    /**
     * ctrl+o 创建无参构造的方法(object)
     *
     */
    public MessagePrinter() {
        super();
        System.out.println("MessagePrinter");

    }

    /**
     * private 建立MessagePrinter 和 MessagesService 关联关系
     */
    private MessagesService service;

    /**
     * service setter 方法 选择service 按住alt+insert 选择setter
     * 设置service的值
     * @param service
     * @Autowired 用于spring管理对象之间的关联关系
     */

    @Autowired
    public void setService(MessagesService service) {
        this.service = service;
    }

    public void  printMessage(){

        System.out.println(this.service.getMessage());
    }
}

ApplicationSpring

package hello;


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

/**
 * 创建Application来调用MessagePrinter类
 * @ComponentScan 扫描@Component注解的类
 */
@ComponentScan
public class ApplicationSpring {

    public static void main(String[] args) {



        System.out.println("application");
//
//        //创建打印机对象
//        MessagePrinter printer = new MessagePrinter();
//        //创建消息服务对象
//        MessagesService service = new MessagesService();
//        //设置打印机的service属性
//        printer.setService(service);
//
//        //打印消息
//        printer.printMessage();

        //初始化Spring容器
        ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationSpring.class);

        //从容器中获取MessagePrinter对象
        MessagePrinter printer = context.getBean(MessagePrinter.class);
        //从容器中获取MessagesService对象
        //MessagesService service = context.getBean(MessagesService.class);

        //System.out.println(printer);
        //System.out.println(service);

        //设置打印机的service属性,printer和service 建立关联关系
        //printer.setService(service);
        //打印消息调用printMessage打印
        printer.printMessage();
    }
}

注解:使用@Autowired管理对象之间的关联关系,这样就可以自动处理关联关系。

3.2.2 构造函数方法进行依赖注入

注入的效率最高

Power 新建power方法

package soundsystem;

import org.springframework.stereotype.Component;

@Component
public class Power {
    public Power() {
        super();

    }

    public void supply(){
        System.out.println("电源供电中。。。。。");
    }
}

CDPlayer 增加power注入

package soundsystem;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * Component 让他能被spring上下文发现
 */

@Component
public class CDPlayer {

    /**
     *private 成员变量
     */
    private CompactDisc cd;

    private Power power;

    public CDPlayer() {
        super();
        System.out.println("CDPlayer无参数构造函数");
    }

    /**
     * Ctrl + Insert 选(Constructor)创建有参的构造函数
     * @param
     */

//    @Autowired
//    public CDPlayer(CompactDisc cd, Power power) {
//        this.cd = cd;
//        this.power = power;
//        System.out.println("CDPlayer多参数构造函数");
//    }

    @Autowired
    public CDPlayer(CompactDisc cd, Power power) {
        this.cd = cd;
        this.power = power;
        System.out.println("CDPlayer多参数构造函数。。。。");
    }

    /**
     * 定义一个方法play,执行cd.play() power.supply();播放工作
     */
    public void play(){
        power.supply();
        cd.play();
    }
}

CompactDisc 无修改

package soundsystem;

import org.springframework.stereotype.Component;

@Component
public class CompactDisc {

    public CompactDisc() {
        super();
        System.out.println("CompactDisc无参构造函数");
    }

    public void play(){

        System.out.println("正在播放音乐......");
    }
}

AppConfig 无修改

package soundsystem;


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


/**
 * 这就是一个配置类
 */

@Configuration
@ComponentScan
public class AppConfig {
    public AppConfig() {
        super();
        System.out.println("配置类,用于将注解和主类解耦");
    }
}

AppTest 无修改

package soundsystem;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class AppTest {

    @Autowired
    private CDPlayer player;

    @Test
    public void testPlay(){

        player.play();
    }

}
3.2.3 用成员变量的方式进行依赖注入

这个方式就是spring通过反射机制做的依赖注入

注入效率低,但是简洁

package soundsystem;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * Component 让他能被spring上下文发现
 */

@Component
public class CDPlayer {

    /**
     *private 成员变量
     */
    @Autowired
    private CompactDisc cd;

    @Autowired
    private Power power;

    public CDPlayer() {
        super();
        System.out.println("CDPlayer无参数构造函数");

    }

    /**
     * Ctrl + Insert 选(Constructor)创建有参的构造函数
     * @param
     */

//    @Autowired
//    public CDPlayer(CompactDisc cd) {
//        this.cd = cd;
//        System.out.println("CDPlayer有参数构造函数");
//    }

//    @Autowired
//    public CDPlayer(CompactDisc cd, Power power) {
//        this.cd = cd;
//        this.power = power;
//        System.out.println("CDPlayer多参数构造函数。。。。");
//    }

    /**
     * 定义一个方法play,执行cd.play()播放工作
     */
    public void play(){
        power.supply();
        cd.play();
    }
}
3.2.3 利用setter方法进行依赖注入

Alt+Insert 选setter进行setter对对象方法进行装配

package soundsystem;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * Component 让他能被spring上下文发现
 */

@Component
public class CDPlayer {

    /**
     *private 成员变量
     */
    //@Autowired
    private CompactDisc cd;

    //@Autowired
    private Power power;

    @Autowired
    public void setCd(CompactDisc cd) {
        this.cd = cd;
        System.out.println("调用setCd。。。。");
    }

    @Autowired
    public void setPower(Power power) {
        this.power = power;
        System.out.println("调用setPower。。。");
    }

    public CDPlayer() {
        super();
        System.out.println("CDPlayer无参数构造函数");

    }

    /**
     * Ctrl + Insert 选(Constructor)创建有参的构造函数
     * @param
     */

//    @Autowired
//    public CDPlayer(CompactDisc cd) {
//        this.cd = cd;
//        System.out.println("CDPlayer有参数构造函数");
//    }

//    @Autowired
//    public CDPlayer(CompactDisc cd, Power power) {
//        this.cd = cd;
//        this.power = power;
//        System.out.println("CDPlayer多参数构造函数。。。。");
//    }

    /**
     * 定义一个方法play,执行cd.play()播放工作
     */
    public void play(){
        power.supply();
        cd.play();

    }

}
3.2.4 用在任意方法上
package soundsystem;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * Component 让他能被spring上下文发现
 */

@Component
public class CDPlayer {

    /**
     *private 成员变量
     */
    //@Autowired
    private CompactDisc cd;

    //@Autowired
    private Power power;

//    @Autowired
//    public void setCd(CompactDisc cd) {
//        this.cd = cd;
//        System.out.println("调用setCd。。。。");
//    }
//
//    @Autowired
//    public void setPower(Power power) {
//        this.power = power;
//        System.out.println("调用setPower。。。");
//    }
    @Autowired
    public void prepare(CompactDisc cd ,Power power){
        this.cd = cd;
        this.power = power;
        System.out.println("调用prepare。。。");

    }

    public CDPlayer() {
        super();
        System.out.println("CDPlayer无参数构造函数");

    }

    /**
     * Ctrl + Insert 选(Constructor)创建有参的构造函数
     * @param
     */

//    @Autowired
//    public CDPlayer(CompactDisc cd) {
//        this.cd = cd;
//        System.out.println("CDPlayer有参数构造函数");
//    }

//    @Autowired
//    public CDPlayer(CompactDisc cd, Power power) {
//        this.cd = cd;
//        this.power = power;
//        System.out.println("CDPlayer多参数构造函数。。。。");
//    }

    /**
     * 定义一个方法play,执行cd.play()播放工作
     */
    public void play(){
        power.supply();
        cd.play();

    }

}
4.接口开发 interface 4.1 简单的接口实现,单一实现类环境

创建com.cloud.demo.service 包

创建UserService 接口

package com.cloud.demo.service;


/**

*/
public interface UserService {

  void add();

}

- 创建接口实现方法(实现类),创建包com.cloud.demo.service.com.cloud.demo.service.impl,创建实现类UserServiceNormal

package com.cloud.demo.service.com.cloud.demo.service.impl;

import com.cloud.demo.service.UserService;
import org.springframework.stereotype.Component;

/**

UserServiceNormal 实现UserService 的方法

这里为实现类,@Component不写在接口,写在实现类上

*/

@Component
public class UserServiceNormal implements UserService {

  public void add() {
      System.out.println("添加用户");

  }

}

- 创建配置类AppConfig

package com.cloud.demo.service;

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

@Configuration
@ComponentScan
public class AppConfig {

}



- 创建单元测试,新建包com.cloud.demo.service,userService的接口UserServiceTest

package com.cloud.demo.service;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**

1.要测试的是userService的接口

2.private UserService userService; 接口注入@Autowired

3.userService.add() 调用add()方法

*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class UserServiceTest {

  //单一实现类环境下
  @Autowired
  private UserService userService;

  @Test
  public void testAdd(){
      userService.add();
  }

}

***@Component不写在接口,写在实现类上***

***调用userService,需要声明接口 private UserService userService;***

### 4.2 多实现类环境

#### 4.2.1 设置首选Bean

- 配置@Primary,这样系统默认就会使用UserServiceNormal实现类,但是有局限性
- 只能定义一个@Primary

@Component
@Primary
public class UserServiceNormal implements UserService {

public void add() {
    System.out.println("增加用户");
}

public void del() {
    System.out.println("删除用户");
}

}

#### 4.2.2 使用限定符@Qualifier

UserServiceFestival

@Component
@Qualifier("Festival")
public class UserServiceFestival implements UserService {

@Override
public void add() {
    System.out.println("注册用户并发送优惠券");
}

@Override
public void del() {

}

}

UserServiceNormal

@Component
@Qualifier("Normal")
public class UserServiceNormal implements UserService {

public void add() {
    System.out.println("增加用户");
}

public void del() {
    System.out.println("删除用户");
}

}

UserServiceTest

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class UserServiceTest {

@Autowired
//这里通过@Qualifier 调用Festival 实现类
@Qualifier("Festival")
private UserService userService;

@Test
public void testAdd(){
    userService.add();
    userService.del();
}

}

#### 4.2.3 通过设置ID和限定符实现

- 将参数配置在@Component中实现@Qualifier

UserServiceFestival

@Component("fastival")
public class UserServiceFestival implements UserService {

@Override
public void add() {
    System.out.println("注册用户并发送优惠券");
}

@Override
public void del() {

}

}

UserServiceNormal

@Component("normal")
public class UserServiceNormal implements UserService {

public void add() {
    System.out.println("增加用户");
}

public void del() {
    System.out.println("删除用户");
}

}

UserServiceTest

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class UserServiceTest {

@Autowired
@Qualifier("fastival")
private UserService userService;

@Test
public void testAdd(){
    userService.add();
    userService.del();
}

}

#### 4.2.4 使用系统默认ID和限定符

- spring中默认会给实现类分配一个ID ,为类名首写字母小写

UserServiceTest

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class UserServiceTest {

@Autowired
@Qualifier("userServiceNormal")
private UserService userService;

@Test
public void testAdd(){
    userService.add();
    userService.del();
}

}

#### 4.2.5 使用@Resource

- @Resource 相当于@Autowired + @Qualifier("userServiceNormal")
- @Resource是jdk标准类,非spring标准类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class UserServiceTest {

//@Autowired
//@Qualifier("userServiceNormal")
@Resource(name="userServiceNormal")
private UserService userService;


@Test
public void testAdd(){
    userService.add();
    userService.del();
}

}

## 5.配置类 ComponentScan组件扫描

### 5.1 直接声明

直接声明单个目录

@Configuration
@ComponentScan("com.cloud.demo")



直接声明多个目录

@Configuration
@ComponentScan(basePackages = {"com.cloud.demo.web","com.cloud.demo.service","com.cloud.demo.dao"})

- 有风险重构不会自动修改



直接声明接口类

@Configuration
@ComponentScan(basePackageClasses = {UserController.class, UserService.class, UserDao.class})

### 5.2 XML声明

***applicationContext.xml 相当于@Configuration***

applicationContext.xml


   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">

    

***测试用列中修改UserControllerTest***

@ContextConfiguration("classpath:applicationContext.xml") 指定xml位置

@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(classes = AppConfig.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class UserControllerTest {

@Autowired
private UserController userController;

@Test
public void testAdd(){
    userController.add();

}

}

## 6 配置Java Configuration

### 6.1 如何配置@bean对象在java Config

接口:UserDao

public interface UserDao {

void add();

}

接口实现类:UserDaoNormal

public class UserDaoNormal implements UserDao {

@Override
public void add() {

    System.out.println("添加用户到数据库中。。。。");

}

}

配置类:AppConfig

- @Configuration 声明为配置类
- @Bean标识spring默认启动会自动加载改配置

@Configuration
public class AppConfig {

@Bean
public UserDao UserDaoNormal(){
    System.out.println("创建UserDao对象");

    return new UserDaoNormal();
}

}

测试类:UserDaoTest

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class UserDaoTest {

@Autowired
private UserDao userDao;

@Test
public void testAdd(){

    userDao.add();
}

}

### 6.2 构造函数注入场景- 普通方式

UserServiceNormal 

- 通过构造函数关联依赖

public class UserServiceNormal implements UserService {

private UserDao userDao;

//无参构造函数
public UserServiceNormal() {
    super();
}

//有参构造函数
public UserServiceNormal(UserDao userDao) {
    this.userDao = userDao;
}

@Override
public void add() {
    userDao.add();

}

}

UserService

public interface UserService {

void add();

}

UserDao

public interface UserDao {

void add();

}

UserDaoNormal

public class UserDaoNormal implements UserDao {

@Override
public void add() {

    System.out.println("添加用户到数据库中。。。。");

}

}

AppConfig

@Configuration
public class AppConfig {

@Bean
public UserDao userDaoNormal(){
    System.out.println("创建UserDao对象");

    return new UserDaoNormal();
}

@Bean
public UserService userServiceNormal(){
    System.out.println("创建UserService对象");
    UserDao userDao = userDaoNormal();
    return new UserServiceNormal(userDao);
}

}

UserServiceTest

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class UserServiceTest {

@Autowired
private UserService userService;

@Test
public void testAdd(){

    userService.add();
}

}

### 6.3 构造函数注入场景- 优雅方式

AppConfig

@Configuration
public class AppConfig {

@Bean
public UserDao userDaoNormal(){
    System.out.println("创建UserDao对象");

    return new UserDaoNormal();
}

@Bean
public UserService userServiceNormal(UserDao userDao){
    System.out.println("创建UserService对象");
    
    //UserDao userDao = userDaoNormal();
    return new UserServiceNormal(userDao);
}

}

- 实际编程中不会做函数的调用,而是在参数中取获取UserDao

### 6.4 通过setter方法依赖注入

UserServiceNormal

public class UserServiceNormal implements UserService {

private UserDao userDao;

//setter方法注入
public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
}

@Override
public void add() {
    userDao.add();

}

}

AppConfig

@Configuration
public class AppConfig {

@Bean
public UserDao userDaoNormal(){
    System.out.println("创建UserDao对象");

    return new UserDaoNormal();
}

@Bean
public UserService userServiceNormal(UserDao userDao){
    System.out.println("创建UserService对象");
    //赋值给一个变量userService
    UserServiceNormal userService = new UserServiceNormal();
    //调用userService的setter方法,将userDao注入
    userService.setUserDao(userDao);
    //返回userService
    return userService;

}

}

### 6.5 通过任意函数注入

UserServiceNormal

public class UserServiceNormal implements UserService {

private UserDao userDao;

//任意函数注入
public void prepare(UserDao userDao){
    this.userDao = userDao;
}

@Override
public void add() {
    userDao.add();

}

}

AppConfig

@Configuration
public class AppConfig {

@Bean
public UserDao userDaoNormal(){
    System.out.println("创建UserDao对象");

    return new UserDaoNormal();
}

@Bean
public UserService userServiceNormal(UserDao userDao){
    System.out.println("创建UserService对象");
    UserServiceNormal userService = new UserServiceNormal();
    //任意函数注入
    userService.prepare(userDao);
    return userService;

}

}

### 6.6 XML装配

#### 6.6.1 创建xml配置规范

applicationContext.xml


   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">

#### 6.6.2 xml定义第bean

CompactDisc

public class CompactDisc {

public CompactDisc() {
    super();
    System.out.println("CompacDisc构造函数。。。。" + this.toString());
}

public void play(){
    System.out.println("播放CD音乐。。。。。" + this.toString());

}

}

ApplicationSpring

public class ApplicationSpring {

public static void main(String[] args) {
    System.out.println("ApplicationSpring is running......");

    ClassPathXmlApplicationContext context =  new ClassPathXmlApplicationContext("applicationContext.xml");
    //初始化cd
    CompactDisc cd = context.getBean(CompactDisc.class);
    //调用play方法
    cd.play();
}

}

applicationContext.xml

- xml 定义bean


   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">

输出结果

ApplicationSpring is running......
CompacDisc构造函数。。。。com.cloud.deam.soundsystem.CompactDisc@2669b199
播放CD音乐。。。。。com.cloud.deam.soundsystem.CompactDisc@2669b199



***多个重名bean设置id区分:***


- name可以通过分号、空格、逗号分隔,设置不同的别名 name="CompactDisc1 CompactDisc12 CompactDisc13  "
- id只能通过传字符进行传递

ApplicationSpring -- 主方法

public class ApplicationSpring {

public static void main(String[] args) {
    System.out.println("ApplicationSpring is running......");

    ClassPathXmlApplicationContext context =  new ClassPathXmlApplicationContext("applicationContext.xml");
    //CompactDisc cd = context.getBean(CompactDisc.class);

    CompactDisc cd1 = (CompactDisc) context.getBean("compactDisc1");
    CompactDisc cd2 = (CompactDisc) context.getBean("compactDisc2");
    
    cd1.play();      
    cd2.play();
}

}

AppTest -- 测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class CompactDiscTest {

@Autowired
private CompactDisc CompactDisc1;

@Autowired
private CompactDisc CompactDisc2;

//过滤方式注入
@Autowired
@Qualifier("CompactDisc2")
private CompactDisc cd;


@Test
public void testPlay(){
    CompactDisc1.play();
    CompactDisc2.play();
    cd.play();
}

}

#### 6.6.3 xml注入 - 通过构造函数

| 名称                  | 用途                                                         | 备注 |
| --------------------- | ------------------------------------------------------------ | ---- |
| 元素 | 依赖Bean,有参构造函数依赖注入                               |      |
| c-名称空间            | --c:c函数命令空间 :cd 构造函数的参数名字cd
public CDPlayer(CompactDisc cd),-ref:表示的是CompactDisc2名称的引用
也可以写成c:0-ref="CompactDisc2" c:1-ref="CompactDisc2" 表示第一个 第二个参数 | | | | | | ***元构造函数依赖注入*** applicationContext.xml

    
            
CDPlayerTest

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class CDPlayerTest {

@Autowired
private CDPlayer cdPlayer;

@Test
public void Test01(){

    cdPlayer.play();
}

}

***c-名称空间依赖注入***


   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">




    



CDPlayerTest

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class CDPlayerTest {

@Autowired
private CDPlayer cdPlayer1;

@Autowired
private CDPlayer cdPlayer2;

@Test
public void Test01(){

    cdPlayer1.play();
    cdPlayer2.play();
}

}

#### 6.6.4 注入简单类型 -通过构造函数

- 给CompactDisc1 对象注入title、artist

    
    

    
    
***-c方式注入简单类型:***
CompactDisc

public class CompactDisc {

private String title;
private String artist;


public CompactDisc() {
    super();
    System.out.println("CompacDisc构造函数。。。。" + this.toString());
}



public CompactDisc(String title, String artist) {
    this.title = title;
    this.artist = artist;

    System.out.println("CompacDisc构造函数。。。。" + this.toString());
}

public void play(){
    System.out.println("播放CD音乐。。。。。" + this.toString() +" " +this.title+ " by " +this.artist);

}

}

#### 6.6.5  注入list类型 -通过构造函数

applicationContext.xml

    
    
    
        
            I Do 1
            I Do 2
            I Do 3
        
    
CompactDisc

public class CompactDisc {

private String title;
private String artist;

//声明一个list
private List tracks;


public CompactDisc() {
    super();
    System.out.println("CompacDisc构造函数。。。。" + this.toString());
}



public CompactDisc(String title, String artist) {
    this.title = title;
    this.artist = artist;

    System.out.println("CompacDisc有参构造函数。。。。" + this.toString());
}

//创建包含三个函数的构造函数
public CompactDisc(String title, String artist, List tracks) {
    this.title = title;
    this.artist = artist;
    this.tracks = tracks;

    System.out.println("CompacDisc有三个参构造函数。。。。" + this.toString());
}

public void play(){
    System.out.println("播放CD音乐。。。。。" + this.toString() +" " +this.title+ " by " +this.artist);
    
   //循环打印tracks内容
    for (String track : this.tracks) {
        System.out.println("音乐:" + track);
    }

}

}

***创建一个复杂对象类型***

创建类型 Music 

package com.cloud.deam.soundsystem;

public class Music {

private String title;
private Integer duration;

//创建getter setter 方法
public String getTitle() {
    return title;
}

public void setTitle(String title) {
    this.title = title;
}

public Integer getDuration() {
    return duration;
}

public void setDuration(Integer duration) {
    this.duration = duration;
}

//创建无参构造方法

public Music() {
    super();
}

//创建有参构造方法
public Music(String title, Integer duration) {
    this.title = title;
    this.duration = duration;
}

}

CompactDisc

public class CompactDisc {

private String title;
private String artist;

//设置List为Music类型
private List tracks;


public CompactDisc() {
    super();
    System.out.println("CompacDisc构造函数。。。。" + this.toString());
}



public CompactDisc(String title, String artist) {
    this.title = title;
    this.artist = artist;

    System.out.println("CompacDisc有参构造函数。。。。" + this.toString());
}

//设置List为Music类型
public CompactDisc(String title, String artist, List tracks) {
    this.title = title;
    this.artist = artist;
    this.tracks = tracks;

    System.out.println("CompacDisc有三个参构造函数。。。。" + this.toString());
}

public void play(){
    System.out.println("播放CD音乐。。。。。" + this.toString() +" " +this.title+ " by " +this.artist);

    for (Music track : this.tracks) {
        //通过get方法获取属性
        System.out.println("音乐:" + track.getTitle() + ".时长:" + track.getDuration());

    }

}

}

applicationContext.xml

- 复杂的对象依赖注入

    
    



    
    



    
    



    
    
    
        
            
            
            
        
    
#### 6.6.6 注入set类型 -通过构造函数

CompactDisc

public class CompactDisc {

private String title;
private String artist;

//设置set为Music类型
private List tracks;


public CompactDisc() {
    super();
    System.out.println("CompacDisc构造函数。。。。" + this.toString());
}



public CompactDisc(String title, String artist) {
    this.title = title;
    this.artist = artist;

    System.out.println("CompacDisc有参构造函数。。。。" + this.toString());
}

//设置set为Music类型
public CompactDisc(String title, String artist, set tracks) {
    this.title = title;
    this.artist = artist;
    this.tracks = tracks;

    System.out.println("CompacDisc有三个参构造函数。。。。" + this.toString());
}

public void play(){
    System.out.println("播放CD音乐。。。。。" + this.toString() +" " +this.title+ " by " +this.artist);

    for (Music track : this.tracks) {
        //通过get方法获取属性
        System.out.println("音乐:" + track.getTitle() + ".时长:" + track.getDuration());

    }

}

}

applicationContext.xml

    
    



    
    



    
    




    
    
    
        
        
            
            
            
        
    
- ***set和list区别在装配的时候重复的值在set中会被过滤***
- ***set元素的顺序能够和插入一致。而list是无序的***



#### 6.6.7 注入MAP集合 -通过构造函数

CompactDisc

public class CompactDisc {

private String title;
private String artist;
private Map tracks;


public CompactDisc() {
    super();
    System.out.println("CompacDisc构造函数。。。。" + this.toString());
}

public CompactDisc(String title, String artist) {
    this.title = title;
    this.artist = artist;

    System.out.println("CompacDisc有参构造函数。。。。" + this.toString());
}

public CompactDisc(String title, String artist, Map tracks) {
    this.title = title;
    this.artist = artist;
    this.tracks = tracks;

    System.out.println("CompacDisc有三个参构造函数。。。。" + this.toString());
}

public void play(){
    System.out.println("播放CD音乐。。。。。" + this.toString() +" " +this.title+ " by " +this.artist);

    for (String key : this.tracks.keySet()) {
        System.out.println("key:" + key );
        Music music = this.tracks.get(key);
        System.out.println("音乐:" + music.getTitle() + ".时长:" + music.getDuration());
    }
}

}

applicationContext.xml

    
    



    
    



    
    




    
    
    
        
        //map类型注入需要使用entry
        
            
            
            
        
    
#### 6.6.8 注入数组类型 -通过构造函数

CompactDisc

public class CompactDisc {

private String title;
private String artist;
//设置Music为数组类型
private Music[] tracks;


public CompactDisc() {
    super();
    System.out.println("CompacDisc构造函数。。。。" + this.toString());
}



public CompactDisc(String title, String artist) {
    this.title = title;
    this.artist = artist;

    System.out.println("CompacDisc有参构造函数。。。。" + this.toString());
}

//设置Music为数组类型
public CompactDisc(String title, String artist, Music[] tracks) {
    this.title = title;
    this.artist = artist;
    this.tracks = tracks;

    System.out.println("CompacDisc有三个参构造函数。。。。" + this.toString());
}

public void play(){
    System.out.println("播放CD音乐。。。。。" + this.toString() +" " +this.title+ " by " +this.artist);

    for (Music track : this.tracks) {
        System.out.println("音乐:" + track.getTitle() + ".时长:" + track.getDuration());

    }

}

}

applicationContext.xml

    
    



    
    



    
    




    
    
    
        
            
            
            
        
    
#### 6.6.9 属性注入

1.set注入属性注入

applicationContext-properties.xml

- property 注入元素


   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">


    
    




   
   


Music

- 属性注入只需set方法就可以
- 属性的构造方法,会走无参构造函数

public class Music {

//声明的是私有的成员变量
private String title;
private Integer duration;

//创建getter setter 方法
public String getTitle() {
    return title;
}

//setTitle是属性
public void setTitle(String title) {
    this.title = title;
    System.out.println("--在" +this.toString() + "中注入title");
}

public Integer getDuration() {
    return duration;
}

//setDuration是属性
public void setDuration(Integer duration) {
    this.duration = duration;
    System.out.println("--在" +this.toString() + "中注入duration");
}

//创建无参构造方法

public Music() {
    super();
    System.out.println("Music的构造函数。。。"+this.toString());
}

//创建有参构造方法
public Music(String title, Integer duration) {
    this.title = title;
    this.duration = duration;

}

}

AppTest

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-properties.xml")
public class AppTest {

@Test
public void test(){
}

}

测试结果

Music的构造函数。。。com.cloud.deam.soundsys

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/75700.html

相关文章

  • java&javaweb学习笔记(汇总)

    摘要:我的学习笔记汇总标签笔记分为两大部分和笔记内容主要是对一些基础特性和编程细节进行总结整理,适合了解基础语法,想进一步深入学习的人如果觉得不错,请给,这也是对我的鼓励,有什么意见欢迎留言反馈目录基础巩固笔记反射基础巩固笔记泛型基础巩 我的java&javaweb学习笔记(汇总) 标签: java [TOC] 笔记分为两大部分:javase和javaweb javase javawe...

    yagami 评论0 收藏0
  • Java初学者最佳的学习方法以及会遇到的坑(内含学习资料)!

    摘要:最近系统整理了一套初学者最佳的学习方法以及会遇到的坑等,希望对你有所帮助。正常的智商其实,学习并不需要所谓的数学逻辑好,需要英语水平棒。大周期每天学习时间五个小时以上的,建议学习周期。三学习时会遇到的坑不知道学习的重点,下面学习路线会画。 最近系统整理了一套java初学者最佳的学习方法以及会遇到的坑等,希望对你有所帮助。 目录: 一、学习java的前提 二、学习java的方法 三、学习...

    Half 评论0 收藏0
  • Java入门请不要放弃,学习路线以及侧重点分析

    摘要:而面向搜索引擎,就是我们要及时的使用百度谷歌遇到问题无法解决,先别急着放弃,可以去网络寻找答案,你的坑大部分别人都已经走过了,大部分都可以找到合适的解决方案。 showImg(https://segmentfault.com/img/remote/1460000019236352?w=866&h=456); 前言: ●众多的语言,到底哪一门才是适合我的?●我们为什么要学习Java语言呢...

    mochixuan 评论0 收藏0
  • ApacheCN 编程/大数据/数据科学/人工智能学习资源 2019.6

    摘要:请回复这个帖子并注明组织个人信息来申请加入。权限分配灵活,能者居之。数量超过个,在所有组织中排名前。网站日超过,排名的峰值为。导航归档社区自媒体平台微博知乎专栏公众号博客园简书合作侵权,请联系请抄送一份到赞助我们 Special Sponsors showImg(https://segmentfault.com/img/remote/1460000018907426?w=1760&h=...

    Bmob 评论0 收藏0
  • ApacheCN 编程/大数据/数据科学/人工智能学习资源 2019.5

    摘要:请回复这个帖子并注明组织个人信息来申请加入。版笔记等到中文字幕翻译完毕后再整理。数量超过个,在所有组织中排名前。网站日超过,排名的峰值为。主页归档社区自媒体平台微博知乎专栏公众号博客园简书合作侵权,请联系请抄送一份到赞助我们 Special Sponsors showImg(https://segmentfault.com/img/remote/1460000018907426?w=1...

    zhonghanwen 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<