研究报告 | 每日更新目录2021.08.21

459. 重复的子字符串

  返回  

spring系列(一)之ioc

2021/8/21 19:25:02 浏览:

1.ioc概述

ioc中文名叫控制反转,实际上是指一个对象控制权的反转。
使用spring后可以将对象的创建、初始化、销毁都交给spring容器管理,要使用该对象时直接从spring容器中获取,不用重新去创建,可以有效降低对象之间的耦合。

2.ioc初见

2.1.创建一个maven项目,添加ioc依赖。

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.8.RELEASE</version>
</dependency>

2.2.创建测试类User 。

public class User {
    private int id;

    private String name;
    //忽略set/get/toString方法

2.3创建applicationContext.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" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="User" class="com.teasir.bean.User" >
     <constructor-arg name="id" value="1"/>
        <constructor-arg name="name" value="teasir"/>
    </bean>
</beans>

2.4.在main方法中加载配置文件并测试

public static void main(String[] args) {
        //ClassPathXmlApplicationContext去classpath路径下去寻找配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //建议直接通过id或者name的形式获得bean
        User user = (User) context.getBean("User");
        System.out.println(user);
        }

2.5控制台输出

User{id=1, name='teasir'}

3.获得bean的其他方式

3.1.在ioc初见中,我们通过id或name来获取实例,其实也可以通过Class来获取实例。

public static void main(String[] args) {
        //ClassPathXmlApplicationContext去classpath路径下去寻找配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //通过User.class,如果有两个相同的类会报错
        User user=(User)context.getBean(User.class);
        System.out.println(user);
        }

3.2但通过Class来获取实例在测试文件不能出现相同的实例,否则会报错:

Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.teasir.bean.User' available: expected single matching bean but found 2: User,User1
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1200)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:420)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:350)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:343)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1127)
	at com.teasir.test.UserTest.main(UserTest.java:13)

3.3所以建议直接通过id或者name的形式获得bean。

4.属性的注入

在xml的配置中,有多种方式可以注入属性。
4.1.构造器注入

<bean id="User" class="com.teasir.bean.User" scope="prototype">
        <!--index定位-->
        <!-- <constructor-arg index="0" value="1"/>
         <constructor-arg index="1" value="teasir"/>-->
        <!--name定位-->
        <constructor-arg name="id" value="1"/>
        <constructor-arg name="name" value="teasir"/>
    </bean>

测试及控制台输出

        //ClassPathXmlApplicationContext去classpath路径下去寻找配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //建议直接通过id或者name的形式获得bean
        User user = (User) context.getBean("User");
        System.out.println(user);
User{id=1, name='teasir'}

4.2.set方法注入

    <bean id="User1" class="com.teasir.bean.User">
        <property name="id" value="2"/>
        <property name="name" value="javaboy"/>
    </bean>

测试及控制台输出

        //ClassPathXmlApplicationContext去classpath路径下去寻找配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //建议直接通过id或者name的形式获得bean
        User user1 = (User) context.getBean("User1");
        System.out.println(user1);
User{id=2, name='javaboy'}

4.3.p空间注入

<!--p名称空间注入-->
    <bean id="User2" class="com.teasir.bean.User" p:id="3" p:name="p名称空间注入">
    </bean>

测试及控制台输出

 //ClassPathXmlApplicationContext去classpath路径下去寻找配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //建议直接通过id或者name的形式获得bean
        User user2 = (User) context.getBean("User2");
        System.out.println(user2);
User{id=3, name='p名称空间注入'}

4.4.外部Bean注入
比如在OkHttp的网络请求中,我们要使用它的实例没有构造方法,只能通过Builder来获得。
我们可以通过静态工厂和实例工厂两种方式来给OkHttp提供一个实例。
(1)静态工厂
我们首先创建一个静态工厂工具类。

package com.teasir.bean;

import okhttp3.OkHttpClient;

public class OkHttpsUtils {
    private static OkHttpClient okHttpClient;

    //创建一个静态工厂
    public static OkHttpClient getInstance() {
        if (okHttpClient == null) {
            okHttpClient = new OkHttpClient.Builder().build();
        }
        return okHttpClient;
    }
}

在xml中配置该实例,下面配置的意思是可以通过OkHttpsUtils类的getInstance方法获得okHttpClient实例。

<!--静态工厂配置实例-->
    <bean class="com.teasir.bean.OkHttpsUtils" factory-method="getInstance" id="okHttpClient"></bean>

测试及控制台输出
这段测试代码能实现将配置的url里的图片内容存储在本地配置地址的图片中。

public static void main(String[] args) {
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        OkHttpClient okHttpClient=context.getBean("okHttpClient", OkHttpClient.class);
        //OkHttpClient okHttpClient=new OkHttpClient.Builder().build();
        Request request=new Request.Builder().get().url("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fn.sinaimg.cn%2Fsinacn10113%2F248%2Fw2048h1400%2F20190807%2F958e-iaxiufn4174367.jpg&refer=http%3A%2F%2Fn.sinaimg.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1630765697&t=ce5863ec3647b89d2b98a163b795243d").build();
        Call call=okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            public void onFailure(Call call, IOException e) {
                System.out.println(e.getMessage());
            }

            public void onResponse(Call call, Response response) throws IOException {
                FileOutputStream out=new FileOutputStream(new File("D:\\3F3A0039.jpg"));
                int len;
                byte[]buf=new byte[1024];
                InputStream is=response.body().byteStream();
                System.out.println("-----通信进行中----");
                while ((len=is.read(buf))!=-1){
                    out.write(buf,0,len);

                }
                out.close();
                is.close();

            }
        });
    }
-----通信进行中----

(2)实例工厂
需要先提供该工厂方法的实例,再调用该方法。
实例工厂类。

public class OkHttpsUtils {
    private static OkHttpClient okHttpClient;


    //创建实例工厂
    public  OkHttpClient getInstance() {
        if (okHttpClient == null) {
            okHttpClient = new OkHttpClient.Builder().build();
        }
        return okHttpClient;
    }
}

xml配置

  <!--实例工厂的注入-->
    <bean class="com.teasir.bean.OkHttpsUtils" id="okHttpsUtils"/>
    <bean class="okhttp3.OkHttpClient" factory-bean="okHttpsUtils" factory-method="getInstance"
          id="okHttpClient"></bean>

测试及控制台输出

public static void main(String[] args) {
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        OkHttpClient okHttpClient=context.getBean("okHttpClient", OkHttpClient.class);
        //OkHttpClient okHttpClient=new OkHttpClient.Builder().build();
        Request request=new Request.Builder().get().url("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fn.sinaimg.cn%2Fsinacn10113%2F248%2Fw2048h1400%2F20190807%2F958e-iaxiufn4174367.jpg&refer=http%3A%2F%2Fn.sinaimg.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1630765697&t=ce5863ec3647b89d2b98a163b795243d").build();
        Call call=okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            public void onFailure(Call call, IOException e) {
                System.out.println(e.getMessage());
            }

            public void onResponse(Call call, Response response) throws IOException {
                FileOutputStream out=new FileOutputStream(new File("D:\\3F3A0039.jpg"));
                int len;
                byte[]buf=new byte[1024];
                InputStream is=response.body().byteStream();
                System.out.println("-----通信进行中----");
                while ((len=is.read(buf))!=-1){
                    out.write(buf,0,len);

                }
                out.close();
                is.close();

            }
        });
    }
-----通信进行中----

4.5.对象的注入
新建一个Cat类

public class Cat {
    private int id;

    private int age;

   //set/get/toString()方法省略
}

xml配置

    <!--对象注入-->
    <bean class="com.teasir.bean.Cat" id="cat">
        <property name="id" value="1"></property>
        <property name="age" value="4"></property>
    </bean>
    <bean class="com.teasir.bean.User" id="user3">
        <property name="cat" ref="cat"></property>
    </bean>

测试及控制台输出

        //ClassPathXmlApplicationContext去classpath路径下去寻找配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //对象注入
        User user3 = (User) context.getBean("user3");
        System.out.println(user3);
User{cat=Cat{id=1, age=4}}

4.6.数组注入
xml配置

<!--数组注入-->
    <bean class="com.teasir.bean.User" id="user4">
        <property name="cat" ref="cat"></property>
        <property name="favorites">
            <array>
                <value>游泳</value>
                <value>羽毛球</value>
            </array>
        </property>
    </bean>

测试及控制台输出

        //ClassPathXmlApplicationContext去classpath路径下去寻找配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //数组注入
        User user4 = (User) context.getBean("user4");
        System.out.println(user4);
User{favorites=[游泳, 羽毛球]}

4.7.List注入
xml配置

 <!--list-->
    <bean class="com.teasir.bean.User" id="user5">
        <property name="names">
            <list>
                <value>teasir</value>
                <value>javaboy</value>
            </list>
        </property>
        <property name="cats">
            <list>
                <ref bean="cat"></ref>
                <bean class="com.teasir.bean.Cat" id="cat2">
                    <property name="id" value="2"></property>
                    <property name="age" value="6"></property>
                </bean>
            </list>
        </property>
    </bean>

测试及控制台输出

        //ClassPathXmlApplicationContext去classpath路径下去寻找配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //list注入
        User user5 = (User) context.getBean("user5");
        System.out.println(user5);
User{ names=[teasir, javaboy], cats=[Cat{id=1, age=4}, Cat{id=2, age=6}]}

4.7.Map注入
xml配置

<!--map-->
    <bean class="com.teasir.bean.User" id="user6">
        <property name="smap">
            <map>
                <entry key="2" value="可乐"></entry>
                <entry key="3" value="雪碧"></entry>
            </map>
        </property>
    </bean>

测试及控制台输出

        //ClassPathXmlApplicationContext去classpath路径下去寻找配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
     //map注入
        User user6 = (User) context.getBean("user6");
        System.out.println(user6);
User{smap={2=可乐, 3=雪碧}

4.7.properties注入
xml配置

 <!--properties-->
    <bean class="com.teasir.bean.User" id="user7">
        <property name="prop">
            <props>
                <prop key="1">蜜雪冰城</prop>
                <prop key="2">喜茶</prop>
            </props>
        </property>
    </bean>

测试及控制台输出

        //ClassPathXmlApplicationContext去classpath路径下去寻找配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    //prop注入
        User user7 = (User) context.getBean("user7");
        System.out.println(user7);
User{prop={2=喜茶, 1=蜜雪冰城}

5.java配置

不使用一行xml,使用Java将实例注入到spring容器中。
定义一个实例:SayHello

public class SayHello  {
  
    public String sayHello(String str) {
        return str + ":hello";
    }

}

定义一个配置类来代替applicationContext.xml。
@Configuration则表明SayHelloConfig 类是一个配置类。

import com.teasir.bean.SayHello;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
public class SayHelloConfig {
    @Bean
    @Scope("prototype")
    SayHello sayHello() {
        return new SayHello();
    }
}

测试及控制台输出

teasir:hello

6.自动化配置

自动化配置可以通过xml配置和java代码配置两种方式实现。
(1)xml配置

 <!--自动化扫描-->
    <context:component-scan base-package="com.teasir" use-default-filters="true">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

这段配置的目的就是将com.teasir路径下除了带有@Controller注解的所有实例交给spring容器管理。
(2)Java代码配置

@Configuration
@ComponentScan(basePackages = "com.teasir.service")
/*@ComponentScan(basePackages = "com.teasir", useDefaultFilters = true, excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = UserService.class)
})*/
public class UserServiceCfg {

}

7.Bean的作用域

在xml配置或者java配置中多次获取到的Bean,是否是同一个呢?
如果没有进行设置,默认设置的作用域是singleton,多次获取的Bean都是同一个。
Bean的作用域有:singleton、prototype、request、session。
如果设置为prototype,如下:

import com.teasir.bean.SayHello;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class SayHelloConfig {
    @Bean
    @Scope("prototype")
    SayHello sayHello() {
        return new SayHello();
    }
}

测试及控制台输出

public class SayHelloTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SayHelloConfig.class);
        SayHello sayHello = (SayHello) ctx.getBean("sayHello");
        SayHello sayHello1 = (SayHello) ctx.getBean("sayHello");
        System.out.println(sayHello == sayHello1);
    }
}
false

我们可以看出当Bean的作用域设置为prototype时,两次获取的Bean不是同一个。

8.Aware接口
Aware接口可以获取spring容器的详细信息。
比如:要判断容器中是否含有某个实例。

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class SayHello implements ApplicationContextAware {
    private ApplicationContext context;

    public String sayHello(String str) {
        Boolean flag = context.containsBean("sayHello");
        //如果含有该实例,返回true
        System.out.println(flag);
        return str + ":hello";
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }
}

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号