Spring-IOC

1.Spring简介

​ Spring是一个开源框架,它由[Rod Johnson](https://baike.baidu.com/item/Rod Johnson)创建。它是为了解决企业应用开发的复杂性而创建的。

​ 目前是JavaEE开发的灵魂框架。他可以简化JavaEE开发,可以非常方便整合其他框架,无侵入的进行功能增强。

​ Spring的核心就是 控制反转(IoC)和面向切面(AOP) 。

2.IOC控制反转

2.1 概念

​ 控制反转,之前对象的控制权在类手上,现在反转后到了Spring手上。

​ ### 2.2 入门案例

①导入依赖

导入SpringIOC相关依赖

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
②编写配置文件

在resources目录下创建applicationContext.xml文件,文件名可以任意取。但是建议叫applicationContext。

内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">
       
    <!-- class:配置类的全类名     id:配置一个唯一标识 -->
    <bean class="com.sangeng.dao.impl.StudentDaoImpl" id="studentDao"  ></bean>
</beans>
③创建容器从容器中获取对象并测试
    public static void main(String[] args) {

		//1.获取StudentDaoImpl对象
        //创建Spring容器,指定要读取的配置文件路径
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        //从容器中获取对象
        StudentDao studentDao = (StudentDao) app.getBean("studentDao");
        //调用对象的方法进行测试
        System.out.println(studentDao.getStudentById(1));
    }

3.DI依赖注入

​ 依赖注入可以理解成IoC的一种应用场景,反转的是对象间依赖关系维护权。

3.1 set方法注入

在要注入属性的bean标签中进行配置。前提是该类有提供属性对应的set方法。

package com.sangeng.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private String name;
    private int id;
    private int age;
    private Dog dog;
}
package com.sangeng.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dog {
    private String name;
    private int age;
}
    <bean class="com.sangeng.domain.Dog" id="dog">
        <property name="name" value="小白"></property>
        <property name="age" value="6"></property>
    </bean>

    <bean class="com.sangeng.domain.Student" id="student" >
        <!--
            name属性用来指定要设置哪个属性
            value属性用来设置要设置的值
            ref属性用来给引用类型的属性设置值,可以写上Spring容器中bean的id
        -->
        <property name="name" value="东南枝"></property>
        <property name="age" value="20"></property>
        <property name="id" value="1"></property>
        <property name="dog" ref="dog"></property>
    </bean>

3.2 有参构造注入

在要注入属性的bean标签中进行配置。前提是该类有提供对应的有参构造。

    <!--使用有参构造进行注入-->
    <bean class="com.sangeng.domain.Student" id="student2" >
        <constructor-arg name="name" value="自挂东南枝"></constructor-arg>
        <constructor-arg name="age" value="20"></constructor-arg>
        <constructor-arg name="id" value="30"></constructor-arg>
        <constructor-arg name="dog" ref="dog"></constructor-arg>
    </bean>

3.3 复杂类型属性注入

实体类如下:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private int age;
    private String name;
    private Phone phone;
    private List<String> list;
    private List<Phone> phones;
    private Set<String> set;
    private Map<String, Phone> map;
    private int[] arr;
    private Properties properties;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Phone {
    private double price;
    private String name;
    private String password;
    private String path;

}
<bean class="com.sangeng.domain.Phone" id="phone">
        <property name="price" value="3999"></property>
        <property name="name" value="黑米"></property>
        <property name="password" value="123"></property>
        <property name="path" value="qqqq"></property>
    </bean>
    
    <bean class="com.sangeng.domain.User" id="user">
        <property name="age" value="10"></property>
        <property name="name" value="大队长"></property>
        <property name="phone" ref="phone"></property>
        <property name="list">
            <list>
                <value>三更</value>
                <value>西施</value>
            </list>
        </property>

        <property name="phones">
            <list>
                <ref bean="phone"></ref>
            </list>
        </property>

        <property name="set">
            <set>
                <value>setEle1</value>
                <value>setEle2</value>
            </set>
        </property>

        <property name="map">
            <map>
                <entry key="k1" value-ref="phone"></entry>
                <entry key="k2" value-ref="phone"></entry>
            </map>
        </property>

        <property name="arr">
            <array>
                <value>10</value>
                <value>11</value>
            </array>
        </property>

        <property name="properties">
            <props>
                <prop key="k1">v1</prop>
                <prop key="k2">v2</prop>
            </props>
        </property>
    </bean>

4.SPEL

​ 我们可以再配置文件中使用SPEL表达式。写法如下:

        <property name="age" value="#{20}"/>
        <property name="car" value="#{car}"/>

​ 注意:SPEL需要写到value属性中,不能写到ref属性。

5.配置文件

5.1 读取properties文件

​ 我们可以让Spring读取properties文件中的key/value,然后使用其中的值。

①设置读取properties

在Spring配置文件中加入如下标签:指定要读取的文件的路径。

<context:property-placeholder location="classpath:filename.properties"/>

其中的classpath表示类加载路径下。

我们也会用到如下写法:classpath:**.properties 其中的* * 表示文件名任意。

注意:context命名空间的引入是否正确

②使用配置文件中的值

在我们需要使用的时候可以使用${key}来表示具体的值。注意要再value属性中使用才可以。例如:

<property name="propertyName" value="${key}"/>

5.2 引入Spring配置文件

​ 我们可以在主的配置文件中通过import标签的resource属性,引入其他的xml配置文件

<import resource="classpath:applicationContext-book.xml"/>

6.注解开发

​ 为了简化配置,Spring支持使用注解代替xml配置。

7.Spring常用注解

7.0 注解开发准备工作

​ 如果要使用注解开发必须要开启组件扫描,这样加了注解的类才会被识别出来。Spring才能去解析其中的注解。

<!--启动组件扫描,指定对应扫描的包路径,该包及其子包下所有的类都会被扫描,加载包含指定注解的类-->
<context:component-scan base-package="com.sangeng"/>

7.1 IOC相关注解

7.1.1 @Component,@Controller,@Service ,@Repository

​ 上述4个注解都是加到类上的。

​ 他们都可以起到类似bean标签的作用。可以把加了该注解类的对象放入Spring容器中。

​ 实际再使用时选择任意一个都可以。但是后3个注解是语义化注解。

​ 如果是Service类要求使用@Service。

​ 如果是Dao类要求使用@Repository

​ 如果是Controllerl类(SpringMVC中会学习到)要求使用@Controller

​ 如果是其他类可以使用@Component

配置文件如下:

<?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: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">
<!--启动组件扫描,指定对应扫描的包路径,该包及其子包下所有的类都会被扫描,加载包含指定注解的类-->
    <context:component-scan base-package="com.sangeng"></context:component-scan>

</beans>

7.2 DI相关注解

​ 如果一个bean已经放入Spring容器中了。那么我们可以使用下列注解实现属性注入,让Spring容器帮我们完成属性的赋值。

7.2.1 @Value

​ 主要用于String,Integer等可以直接赋值的属性注入。不依赖setter方法,支持SpEL表达式。

例如:

package com.sangeng.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dog {

	// 直接赋值name = “三更草堂” age = 22
    @Value("三更草堂")
    private String name;
    
    @Value("#{19+3}")
    private int age;
    
    // 从配置文件里读取参数
	@Value("${python.path}")
	private String pythonPath;
}
python:
  path: http://localhost:9005/transfer
7.2.2 @AutoWired

​ Spring会给加了该注解的属性自动注入数据类型相同的对象。

例如:

    @Autowired
    private UserDao userDao;

required属性代表这个属性是否是必须的,默认值为true。如果是true的话Spring容器中如果找不到相同类型的对象完成属性注入就会出现异常。

7.2.3 @Qualifier

​ 如果相同类型的bean在容器中有多个时,单独使用@AutoWired就不能满足要求,这时候可以再加上@Qualifier来指定bean的名字从容器中获取bean注入。

例如:

@Service("userService")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserServiceImpl implements UserService {

    @Autowired
    @Qualifier("userDao1")
    private UserDao userDao;
	
	// 直接赋值num = 199  str = “三更草堂” age = 22
    @Value("199")
    private int num;
    @Value("三更草堂")
    private String str;

    @Value("#{19+3}")
    private Integer age;
}
public class MyQualifier {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) app.getBean("userService");
        System.out.println(userService);
    }
}

注意:该直接不能单独使用。单独使用没有作用。@Resource注解name属性可以指定bean

7.3 xml配置文件相关注解

@Configuration

​ 标注在类上,表示当前类是一个配置类。我们可以用注解类来完全替换掉xml配置文件。

​ 注意:如果使用配置类替换了xml配置,spring容器要使用:AnnotationConfigApplicationContext

例如:

@Configuration
public class ApplicationConfig {
}
@ComponentScan

​ 可以用来代替context:component-scan标签来配置组件扫描。

​ basePackages属性来指定要扫描的包。

​ 注意要加在配置类上。

@Configuration
@ComponentScan(basePackages = "com.sangeng")//指定要扫描的包
public class ApplicationConfig {
}
@Bean

​ 可以用来代替bean标签,主要用于第三方类的注入。

​ 使用:定义一个方法,在方法中创建对应的对象并且作为返回值返回。然后在方法上加上@Bean注解,注解的value属性来设置bean的名称。

例如:

@Configuration
@ComponentScan(basePackages = "com.sangeng")
public class ApplicationConfig {

    @Bean("dataSource")
    public DruidDataSource getDataSource(){
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        druidDataSource.setUsername("root");
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/mybatis_db");
        druidDataSource.setPassword("root");
        return druidDataSource;
    }

}

注意事项:如果同一种类型的对象在容器中只有一个,我们可以不设置bean的名称。

具体写法如下:

@Configuration
@ComponentScan(basePackages = "com.sangeng")
public class ApplicationConfig {

    @Bean
    public DruidDataSource getDataSource(){
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        druidDataSource.setUsername("root");
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/mybatis_db");
        druidDataSource.setPassword("root");
        return druidDataSource;
    }

}

获取方式如下:

package com.sangeng;

import com.alibaba.druid.pool.DruidDataSource;
import com.sangeng.config.ApplicationConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import javax.sql.DataSource;


public class Demo {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(ApplicationConfig.class);
        DruidDataSource dataSource = (DruidDataSource) app.getBean(DataSource.class);
        System.out.println(dataSource.getUrl());
    }
}

    }
@PropertySource

​ 可以用来代替context:property-placeholder,让Spring读取指定的properties文件。然后可以使用@Value来获取读取到的值。

使用:在配置类上加@PropertySource注解,注解的value属性来设置properties文件的路径。

然后在配置类中定义成员变量。在成员变量上使用@Value注解来获取读到的值并给对应的成员变量赋值。

例如:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_db
jdbc.username=root
jdbc.password=root

读取文件并且获取值

@Configuration
@ComponentScan(basePackages = "com.sangeng")
@PropertySource("jdbc.properties")
public class ApplicationConfig {

    @Value("${jdbc.driver}")
    private String driverClassName;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;


    @Bean
    public DruidDataSource getDataSource(){
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName(driverClassName);
        druidDataSource.setUsername(username);
        druidDataSource.setUrl(url);
        druidDataSource.setPassword(password);
        return druidDataSource;
    }

}

注意事项:使用@Value获取读到的properties文件中的值时使用的是${key},而不是#{key}。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值