Spring核心知识-Ioc简述(概念和使用)

spring核心两大核心内容为ioc和aop。
本章节讲ioc的概念、作用和使用方式。

ioc简单介绍:

概念:控制反转,把对象创建和对象之间的调用过程,交给Spring管理
目的是降低耦合
底层原理:xml解析、工厂模式、反射
.过程:

  • 1 xml解析得到类的全路径
 ApplicationContext applicationContext =new
                ClassPathXmlApplicationContext("bean.xml");
  • 2 通过反射创建对象
  • 3 通过工厂类返回
   User user  =applicationContext.getBean("user",User .class);

Ioc思想基于ioc容器完成,ioc容器本质上就是对象工厂
spring提供ioc容器实现两种方式:(两个接口)
1.BeanFactory
Ioc容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用
ps:加载配置文件的时候不会创建对象,在获取对象使用才会去创建对象

2.ApplicationContext
有两个实现类:不同在于FileSystemXmlApplicationContext是传绝对路径,ClassPathXmlApplicationContext是传在项目中的相对路径。

ApplicationContext applicationContext =new
                ClassPathXmlApplicationContext("bean.xml");
        User user  =applicationContext.getBean("user",User .class);

ioc管理对象:(指的是创建对象和注入属性
1.基于xml配置文件
2.基于注解方式

基于xml方式:

1.基于xml方式创建对象

使用bean标签 id:唯一属性 class:类全路径

 <bean id="user" class="com.wsl.spring.dao.UserDao" ></bean>

2.基于xml方式注入属性

DI:依赖注入,是ioc注入属性的具体实现

2.1.基于set注入 :使用property注解

 <bean id="user" class="com.wsl.spring.pojo.User" >
        <property name="name" value="小红"></property>
        <property name="age" value="11"></property>
    </bean>

2.2.基于有参构造器注入

<bean id="user" class="com.wsl.spring.pojo.User" >
        <constructor-arg index="0" value="小绿"></constructor-arg>
        <constructor-arg index="1" value="22"></constructor-arg>
    </bean>

如果set注入和构造器注入都写了,先执行构造器,再执行set

2.3.p命名空间注入

可以简化基于xml方式注入
1.在配置文件中添加p命名空间

 <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"** 
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

2.使用p注入

 <bean id="user" class="com.wsl.spring.pojo.User"
    p:age="33" p:name="小兰">
    </bean>

ps:特殊符号处理
1.转义
2.CDATA格式

bean

在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,被称之为bean。简单地讲,bean就是由IoC容器初始化、装配及管理的对象
spring中有两种bean,一种是普通bean,一种是工厂bean FactoryBean (不是beanEactory 不一样的)
普通bean:在配置文件中定义bean类型就是返回类型
工厂bean:在配置文件中定义bean类型可以和返回类型不一样
Step1:创建类,让这个类作为工厂bean,实现接口FactoryBean
Step2:实现接口的方法,在实现的方法中定义返回的类型。

bean的作用域

spring中默认是单实例的,在加载spring配置文件的时候就会创建单实例对象。
设置为prototype的时候,在调用getBean的时候才会创建多实例对象。
Spring核心知识-Ioc简述(概念和使用)_第1张图片

bean的生命周期:

bean对象从创建到销毁的过程。
1.通过构造器创建bean实例
2.为bean的属性设置值和对其他bean的引用(调用set)
3.实现后置处理器,在初始化前做一些工作
4.调用bean的初始化(需要配置初始化方法)init-method配置
5.实现后置处理器,在初始化后做一些工作
6.使用bean
7.当容器关闭,调用bean的销毁方法(需要配置销毁的方法)destroy-method配置

 <bean id="user" class="com.wsl.spring.pojo.User"
    p:age="33" p:name="小兰" init-method="init" destroy-method="destory">
    </bean>

注解方式

@PostConstruct
    protected void init()   {
        System.out.println("init();");
    }
    @PreDestroy
    protected void destory()   {
        System.out.println("destory();");
    }

后置处理器 :实现 BeanPostProcesser 接口 ,可以在初始化前后进行一些处理工作。

外部文件配置bean

1.创建文件jdbc.properties

#============================#
#===== Database sttings =====#
#============================#

#oracle database settings
#jdbc.type=oracle
#jdbc.driver=oracle.jdbc.driver.OracleDriver
#jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
#jdbc.username=jeesite
#jdbc.password=123456

2.引入文件并注入bean

<!-- 加载配置属性文件 -->
	<context:property-placeholder ignore-unresolvable="true" location="classpath:jdbc.properties" />
<!-- bean设置 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
		<!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
		<property name="driverClassName" value="${jdbc.driver}" />

		<!-- 基本属性 url、user、password -->
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />

		<!-- 配置初始化大小、最小、最大 -->
		<property name="initialSize" value="${jdbc.pool.init}" />
		<property name="minIdle" value="${jdbc.pool.minIdle}" />
		<property name="maxActive" value="${jdbc.pool.maxActive}" />

		<!-- 配置获取连接等待超时的时间 -->
		<property name="maxWait" value="60000" />
	</bean>

基于注解方式:

1.开启组件扫描

component-scan 指定注解扫描包
<context:component-scan base-package="com.wsl"></context:component-scan>

或者直接使用@ComponentScan注解

2.在需要扫描的类上面加注解

@Component

@Component("user")
// 相当于配置文件中 

@Component三个衍生注解
为了更好的进行分层,Spring可以使用其它三个注解,功能一样,目前使用哪一个功能都一样。
@Controller:controller层
@Service:service层
@Repository:dao层

3.基于注解实现属性注入

1.@Autowired

在使用@Autowired时,首先在容器中查询对应类型的bean
    如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据
    如果查询的结果不止一个,那么@Autowired会根据名称来查找。
    如果查询的结果为空,那么会抛出异常。解决方法时,使用required=false

2.@Qualifier

@Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配
@Qualifier不能单独使用。

3.@Resource

**@Autowired@Resource异同:
1@Autowired@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。
2@Autowired默认按类型装配(属于spring规范),默认情况下必须要求依赖对象必须存在,
如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) 
,如果我们想使用名称装配可以结合@Qualifier注解进行使用
3@Resource(属于J2EE复返),默认按照名称进行装配,名称可以通过name属性进行指定。
如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在
setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。
但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
它们的作用相同都是用注解方式注入对象,但执行顺序不同。@Autowired先byType,@Resource先byName。**

其他注解:

@Value

用这个注解注入属性
1.直接写值
2.可以写SpEl #{ }
3 ${ } 格式 可以取出配置文件中的值 但需要先用注解@PropertySource(“os.properties”)取到配置文件
、在运行环境变量里面的值

     @Value("小红")
    private String name;
    @Value("#{20-2}")
    private int age;
// 相当于配置文件中 
    @Value(${os.name}) //需要在类上面使用PropertySource注解
    private String os;
 //  类似xml中先用引入外部文件 再用${}取值

@Scope

指定bean作用域:singleton prototype request session

@LazyBean

是针对单实例bean,默认情况下单实例bean是在容器加载的时候创建的。
而懒加载在容器加载时候不创建bean,在第一次使用bean的时候才会创建和初始化。

@Conditional

按照一定的条件进行判断,满足条件向容器注册bean。
可用于类和方法
编写两个类,分别实现Condition接口。

//linux环境下返回true
public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String os = context.getEnvironment().getProperty("os.name");
        return os.contains("Linux");
    }
}
//windows环境下返回true
public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String os =context.getEnvironment().getProperty("os.name");

        return os.contains("Windows");
    }
}

然后在需要判断的bean上加注解@Conditional和用于判断的类名,在满足该类实现的matches方法时,会向容器注册该bean,否则不注册。也可以用于类上面,作用于该类所有的bean。

@Configuration
public class BeanConfig {

    @Conditional(WindowsCondition.class)
    @Bean("windows-张三")
    public User getUser(){
        return new User("windows-张三",11);
    }
    @Conditional(LinuxCondition.class)
    @Bean("linux-张三")
    public User getUser1(){
        return new User("linux-张三",11);
    }
}

@import

快速导入一个组件

@PropertySource

引入外部文件 类似xml中先用

@Primary

在spring 中使用注解,常使用@Autowired, 默认是根据类型Type来自动注入的。但有些特殊情况,对同一个接口,可能会有几种不同的实现类,而默认只会采取其中一种的情况下 @Primary 的作用就出来了,告诉spring 在犹豫的时候优先选择哪一个具体的实现。

@Inject

1、@Inject是JSR330 (Dependency Injection for Java)中的规范,需要导入javax.inject.Inject;实现注入。
2、@Inject是根据类型进行自动装配的,如果需要按名称进行装配,则需要配合@Named;
3、@Inject可以作用在变量、setter方法、构造函数上。
a、将@Inject可以作用在变量、setter方法、构造函数上,和@Autowired一样
b、@Named
@Named(“XXX”) 中的 XX是 Bean 的名称,所以 @Inject和 @Named结合使用时,自动注入的策略就从 byType 转变成 byName 了。

@Profile

指定这个bean在该环境下才能注册到容器中去

自动装配是使用spring满足bean依赖的一种方法
spring会在应用上下文中为某个bean寻找其依赖的bean。
Spring中bean有三种装配机制,分别是:
在xml中显式配置;
在java中显式配置;
隐式的bean发现机制和自动装配。

自动装配:根据指定装配规则(属性名称或者属性类型),将匹配的属性值进行注入。
Spring的自动装配需要从两个角度来实现,或者说是两个操作:
组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;
自动装配(autowiring):spring自动满足bean之间的依赖,也就是我们说的IoC/DI;
组件扫描和自动装配组合发挥巨大威力,使得显示的配置降低到最少。

总结:

给容器中注册组件:

1.包扫描+组件标注注解(@Component @Controller等) 适用于自己编写的类
2.@Bean 用于导入的第三方包里的组件
3.@import 快速导入一个组件
实现ImportSelector 返回需要导入的组件全类名数组
ImportBeanDefinitionRegistrar 手动注册Bean
4.实现Factory接口(工厂bean)
默认获取到的是工厂bean调用getObject创建的对象
要获取工厂bean的本事,需要在id前加一个&符号
5.自定义组件想要使用Spring底层的一些组件,可以实现XXXAware接口注入;每一个XXXAware都有对应的XXXProcesser,为自定义类注入对应Aware。

指定初始化和销毁方法:

1.bean标签的init-method和destory-method
2.bean class实现InitializingBean(定义初始化方法),
实现DisposableBean接口(定义销毁方法)
3.JSR250规范中的@PostConstruct 初始化
@PreDestory 销毁
4。后置处理器 BeanPostProcessor接口
两个方法分别在初始化前后工作

你可能感兴趣的:(spring,java,后端)