Java spring重点归纳(持续更新)

175 阅读7分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

spring引入

1.为什么要用spring?

  • 简化开发---降低了大型项目开发的复杂型。
  • 框架整合---高效整合其他技术,提高大型项目开发与运行效率。

Spring框架的足够灵活受到世界各地开发人员的信任。 无论是流媒体电视、在线购物、还是无数其他创新的解决方案,Spring每天都为数百万终端用户提供愉快的体验。 Spring也有来自所有科技巨头的贡献,包括阿里巴巴、亚马逊、谷歌、微软等。所以,尽情的畅用spring吧~

2.spring核心概念

IOC(Inversion of Control)控制反转

使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转。通俗的讲就是“将new对象的权利交给Spring,我们从Spring中获取对象使用即可”

  • Spring技术对IoC思想进行了实现

    • Spring提供了一个容器,称为IOC容器,用来充当IoC思想中的“外部”
    • IOC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为Bean
  • DI(Dependency Injection)依赖注入

    • 在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入。

3.IoC和注入依赖

需要关注和掌握的是:

  • 如何把定义的类通过xml配置的方式放入IoC容器(Bean)
  • 如何从容器中取出想要的Bean
  • 当A对B产生依赖,在xml中如何表示这个关系 这个部分的知识点,博主就借用之前写的文章来讲解了,《spring之xml配置文件开发》juejin.cn/post/710119… 这篇文章IoC那部分博主写了一个BookDao接口以及它对实现类,然后在xml中写了这个实现类的bean,最后用getBean从容器中拿到这个bean。
<bean id="bookDao" name="dao bookDaoImpl" class="com.springquickstart.dao.impl.BookDaoImpl"></bean>

对于有依赖的两个类,博主新增了BookService接口和它的实现类,在它的实现类中,我们调用了前面BookDao的方法,所以我们BookService的实现类是依赖与我们的BookDao的。那如何表示两者的依赖关系呢?我们需要将两个实现类都丢到IoC容器中,也就是在xml中先写好这两个类的bean,然后使用property标签去配置两者都依赖关系。

<bean id="bookDao" name="dao bookDaoImpl" class="com.springquickstart.dao.impl.BookDaoImpl" ></bean>
<bean id="bookService" name="Service bookService2" class="com.springquickstart.service.impl.BookServiceImpl" >
    <!--DI配置依赖关系-->
    <!--name里面的bookDao指的是bookserviceimpl里面的那个bookDao(依赖对象)名字,ref里的则是bean标签中的-->
    <property name="bookDao" ref="bookDao"></property>
</bean>

前面说的这种依赖是引用类型的依赖(什么是引用类型就默认大家懂了哈),当然还有简单(基本)类型,基本类型的注入方法其实就是property标签中ref属性换成value属性。就像下面这样👇

image.png

Bean

1.Bean的命名与别名


id 属性指定的最多一个名称

name属性中任意数量的其他名称的组合。

这种情况在大型系统中很常见,其中配置在每个子系统之间被分割,每个子系统都有自己的一组对象定义。 在基于xml的配置元数据中,可以使用元素来实现这一点。

alias

<alias name="fromName" alias="toName"/>

子系统A的配置元数据可以以【subsystemA-dataSource】的名称引用数据源。 子系统B的配置元数据可以以【subsystemB-dataSource 】的名称引用数据源。 当编写使用这两个子系统的主应用程序时,主应用程序以【myApp-dataSource】的名称引用数据源。 要使这三个名称都指向同一个对象,您可以向配置元数据添加以下别名定义:

<alias name="myApp-dataSource" alias="subsystemA-dataSource"/>

<alias name="myApp-dataSource" alias="subsystemB-dataSource"/>

现在,每个组件和主应用程序都可以通过唯一的名称来引用dataSource,并且保证不会与任何其他定义(有效地创建了一个名称空间)发生冲突,但它们引用的是相同的bean。

2. 实例化bean

2.1 构造函数实例化

就是最普通的方法实例化bean:写一个类,然后xml配置写bean标签。但这种可能需要一个无参构造,如下

<bean id="exampleBean" class="examples.ExampleBean"/>

<bean name="anotherExample" class="examples.ExampleBeanTwo"/>

2.2 静态工厂实例化

先上一个静态工厂的实例。

public class ClientService {
    private static ClientService clientService = new ClientService();
    private ClientService() {}

    public static ClientService createInstance() {
        return clientService;
    }
}

<bean id="clientService" class="examples.ClientService" factory-method="createInstance"/>

注意: createInstance() 方法必须是一个静态方法

2.3 实例工厂实例化

实例工厂和静态工厂实例化的区别是一个有静态方法,一个没有。使用实例工厂需要有一个实例的bean。factory-bean写上这个实例的bean。如下

<bean id="serviceLocator" class="examples.DefaultServiceLocator">
    <!-- inject any dependencies required by this locator bean -->
</bean>

<bean id="clientService" factory-bean="serviceLocator" factory-method="createClientServiceInstance"/>

<bean id="accountService" factory-bean="serviceLocator" factory-method="createAccountServiceInstance"/>
public class DefaultServiceLocator {

    private static ClientService clientService = new ClientServiceImpl();

    private static AccountService accountService = new AccountServiceImpl();

    public ClientService createClientServiceInstance() {
        return clientService;
    }

    public AccountService createAccountServiceInstance() {
        return accountService;
    }
}  

3. Bean的作用范围

scope描述
singleto每个bean在ioc容器中都是独一无二的单例形式。
prototype将单个beanDifination定义为,spring容器可以【实例化任意数量】的对象实例。
request将单个beanDifination限定为单个HTTP请求的生命周期。 也就是说,每个HTTP请求都有自己的bean实例,它是在单个beanDifination的后面创建的。 仅在web环境中的Spring【ApplicationContext】的上下文中有效。
session将单个beanDifination定义为HTTP 【Session】的生命周期。 仅在web环境中的Spring 【ApplicationContext】的上下文中有效。
application将单个beanDifination定义为【ServletContext】的生命周期。 仅在web环境中的Spring 【ApplicationContext】的上下文中有效。
websocket将单个beanDifination作用域定义为【WebSocket】的生命周期。 仅在web环境中的Spring【ApplicationContext】的上下文中有效。

4. 生命周期

方式一:

< bean id =" exampleInitBean " class =" examples.ExampleBean " init-method =" init "/>

< bean id =" exampleInitBean " class =" examples.ExampleBean " destroy-method =" cleanup "/>

方式2:注解

@PostConstruct

@PreDestroy

为同一个bean配置的多个生命周期机制(具有不同的初始化方法),调用顺序如下:

  1. 用“@PostConstruct”注解的方法
  2. afterPropertiesSet() 由 InitializingBean 回调接口
  3. 自定义配置的init()方法

Destroy方法的调用顺序相同:

  1. 用 @PreDestroy注解的方法
  2. destroy()由 DisposableBean 回调接口定义
  3. 自定义配置的 destroy() 方法

依赖注入

1. 构造函数的依赖注入

package x.y;

public class ThingOne {

    public ThingOne(ThingTwo thingTwo,ThingThree thingThree) {
        // ...
    }
}

1.1 根据参数顺序注入

<beans>
    <bean id="beanOne" class="x.y.ThingOne">
        <!-- 直接写就可以 -->
        <constructor-arg ref="beanTwo"/>
        <constructor-arg ref="beanThree"/>
    </bean>

    <bean id="beanTwo" class="x.y.ThingTwo"/>
    <bean id="beanThree" class="x.y.ThingThree"/>
</beans>

1.2 根据参数类型注入

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>

1.3 按下标注入

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
</bean>

1.4 构造函数参数名字匹配

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>

2. 基于setter的注入

<bean id="exampleBean" class="examples.ExampleBean">
    <!-- setter injection using the nested ref element -->
    <property name="beanOne">
        <ref bean="anotherExampleBean"/>
    </property>

    <!-- setter injection using the neater ref attribute -->
    <property name="beanTwo" ref="yetAnotherBean"/>
    <property name="integerProperty" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean {

    private AnotherBean beanOne;

    private YetAnotherBean beanTwo;

    private int i;

    public void setBeanOne(AnotherBean beanOne) {
        this.beanOne = beanOne;
    }

    public void setBeanTwo(YetAnotherBean beanTwo) {
        this.beanTwo = beanTwo;
    }

    public void setIntegerProperty(int i) {
        this.i = i;
    }
}
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!-- results in a setDriverClassName(String) call -->
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
    <property name="username" value="root"/>
    <property name="password" value="misterkaoli"/>
</bean>

2.1 注入数组类型数据

<property name="array">
    <array>
        <value>100</value>
        <value>200</value>
        <value>300</value>
    </array>
</property>

2.2 注入List类型数据

<property name="list">
    <list>
        <value>itcast</value>
        <value>itheima</value>
        <value>boxuegu</value>
        <value>chuanzhihui</value>
    </list>
</property>

2.3 注入Set类型数据

<property name="set">
    <set>
        <value>itcast</value>
        <value>itheima</value>
        <value>boxuegu</value>
        <value>boxuegu</value>
    </set>
</property>

2.4 注入Map类型数据

<property name="map">
    <map>
        <entry key="country" value="china"/>
        <entry key="province" value="henan"/>
        <entry key="city" value="kaifeng"/>
    </map>
</property>

2.5 注入Properties类型数据

<property name="properties">
    <props>
        <prop key="country">china</prop>
        <prop key="province">henan</prop>
        <prop key="city">kaifeng</prop>
    </props>
</property>

说明:property标签表示setter方式注入,构造方式注入constructor-arg标签内部也可以写、、、、标签

3. 自动装配

配置中使用bean标签autowire属性设置自动装配的类型

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>

基于注解的自动装配@Autowired

@Qualifier微调基于注解的自动装配

@Value注入简单类型

@Component("bookService")
public class BookServiceImpl implements BookService {
    //依赖bookdao
    @Autowired
    @Qualifier("bookDao")
    private BookDao bookDao;
    //注入简单类型
    //@Value("bookdao1")
    @Value("${name}")
    private String name;
    @Override
    public void save() {
        System.out.println("book service save..."+name);
        bookDao.save();
    }
}

@Resource 带有一个name属性。 默认情况下,Spring将该值解释为要注入的bean名。 换句话说,它遵循by-name语义,如下面的示例所示:

public class SimpleMovieLister {
    private MovieFinder movieFinder;
    @Resource(name="myMovieFinder")
    public void setMovieFinder(MovieFinder movieFinder) {
    this.movieFinder = movieFinder;
    } 
}

注解开发常用注解

@Component代替bean注册

@Repository 、@Service @Controller是【@Component】用于更具体用例的注解(分别在持久性、服务和表示层中)。

@Configuration声明配置类,相当于刚生成spring的xml配置最上边那部分。

@ComponentScan写到配置类上方,就是自动扫描指定包中的注解。

@Autowired基于注解的自动装配

@Qualifier微调基于注解的自动装配

@Value注入简单类型

@Scope("prototype") 与xml中bean的scope作用一样

@Bean表示当前方法的返回值是一个bean对象,添加到IOC容器中。

@Import注解导入式

@PropertySource加载properties配置文件@PropertySource({"classpath:jdbc.properties"})

@Bean注解用于指示一个方法,该方法负责【实例化、配置和初始化】一个由Spring IoC容器管理的新对象。 对于那些熟悉Spring XML配置的人来说,@Bean注解扮演着与 元素相同的角色。 你可以在任何Spring @Component中使用@Bean注解方法。 但是,它们最常与@Configuration一起使用。

举例:

public class JdbcConfig {
    //@Bean:表示当前方法的返回值是一个bean对象,添加到IOC容器中
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}
@Configuration
@ComponentScan("com.itheima")
//@Import:导入配置信息
@Import({JdbcConfig.class})
public class SpringConfig {
}

今天就先更新到这里,明天续更。。。。。。