小白初写Spring核心容器功能

Spring核心容器功能

1.spring优点
方便解耦,简化开发
AOP编程的支持
申明式事务的支持
方便程序的测试等等

一,Spring模块架构图
小白初写Spring核心容器功能

  1. core container : 核心容器,是spring框架的基石,任何spring项目运行时都会生成一个容器,把项目运行时需要的对象全部管理起来。创建对象,销毁对象,对象关系的依赖。
  2. test : 测试,可以与junit-4整合起来,测试容器中某些对象。
  3. AOP : 面向切面编程,可以无耦合的给很多方法进行功能的增强。
  4. data access : 数据访问,提供了jdbc模板,可以对数据库进行操作。还可以与其它的ORM框架,如hibernate进行整合使用。
  5. transactions : 事务, spring提供了声明式事务功能,只需要对事务功能进行一次配置,就可以在所有的方法上增加事务。
  6. web - struts : spring的web模块可以和struts框架整合起来使用。
  7. web - mvc : spring开发了自己的一个控制层框架,叫做SpringMVC,代替struts2框架,从开发速度,运行效率上都比struts2要好。

二 Spring核心的两个概念
spring的第一大特性IOC
Inversion Of Controller 控制反转
把创建对象的权利反转交给了spring,这一过程就叫做控制反转
在spring中加载对象,就是通过反射加载
讲个笑话:
什么是IOC? 就是通过反射加载对象的过程
什么是反射? mysql的驱动连接就是通过反射来加载的.

作者:将达吉恩
来源:****
原文:https://blog.****.net/weixin_39836604/article/details/79249684
版权声明:本文为博主原创文章,转载请附上博文链接!

  1. IOC : 控制反转,也叫DI,叫依赖注入。
    控制反转:以前对象都是由程序员自己创建管理的,现在由Spring框架的容器来管理所有的对象。(容器本身也是对象)
    依赖注入:假如Student对象内部有个Clazz属性,就说明学生依赖一个班级。
    把一个clazz对象装入student对象中,这个操作叫注入。spring框架的容器会自动完成依赖注入。
  2. AOP:面向切面(方面)编程。
    解决日志记录,性能统计,安全控制,事务管理功能。共同特点是都要给很多个方法增强功能,增强的功能代码是重复性的。AOP就可以写一遍代码,给所有的方法增强功能。 OOP:面向对象编程。AOP是对OOP的一个补充。

三 内容及方式
1.Spring框架是管理对象的(core container)。
2.Spring框架中管理的对象叫做bean.(
Spring以bean的方式组织和管理Java中的各个组件和关系。
Spring容器通过单例设计模式和工厂设计模式还有反射来加载获取类对象。)
3.在Spring中加载对象就是通过反射加载。
加载对象的三种方式
第一种:通过默认构造器。

无参构造方法创建bean:
<bean id="student"  class="com.youzhong.entity.Student"/>
    使用上面的标签配置bean时,容器调用无参构造方法。

    有参构造方法创建bean:
<bean id="student"  class="com.youzhong.entity.Student">
        <!-- constructor-arg配置构造方法参数 -->
        <!-- index设置参数的索引,value设置参数的值  -->
        <!-- <constructor-arg index="0"  value="20"/> -->
        <!-- name设置参数名 -->
        <!-- <constructor-arg name="id"  value="30"/> -->
        <!-- type设置参数的类型,ref是引用容器中的另一个bean的唯一标识 -->
        <constructor-arg index="0" value="40"/>
        <constructor-arg index="1"  type="java.lang.String" value="张三"/>
        <constructor-arg index="2"  ref="student2"/>
    </bean>
    
    <bean id="student2"  class="com.youzhong.entity.Student"/>

第二种:使用静态工厂来创建对象,需要创建静态工厂类。

我想要电脑:
        方式一:硬盘+主板+内存条+显示器+键盘+鼠标+CPU
        方式二:Thinkpad电脑
    电脑类:
public class Computer {
    private String cpu;
    private String disk;
    private String memory;
    private String board;
    private String keyboard;
    private String mouse;
    静态电脑工厂:
/**
* 静态电脑工厂
* @author Administrator
*
*/
public class ComputerFactory {
    //生产电脑
    //静态方法
    public static Computer createComputer() {
        return new Computer("core-i7","500GB机械","4GB","昂达","机械键盘","雷蛇");
    }
}
    配置spring.xml
<!-- factory-method配置工厂里面的静态方法 -->
    <bean id="computer"  class="com.youzhong.factory.ComputerFactory"  factory-method="createComputer"/>

第三种:通过实例工厂来创建对象,可以在实例工厂初始化对象之前加一些自己的其他操作。

实例工厂创建(了解)
    指工厂里创建对象的方法是普通方法,非static的,只能用对象调用。
    实例工厂:
/**
 1. 实例电脑工厂
 2. @author Administrator
 3. */
public class ComputerFactory {
    
    public ComputerFactory() {
        System.out.println("***********");
    }
    //生产电脑
    //普通方法
    public Computer createComputer() {
        return new Computer("core-i7","500GB机械","4GB","昂达","机械键盘","雷蛇");
    }
}
    配置spring.xml
<!-- 1、创建工厂bean -->
    <bean id="factory"  class="com.youzhong.factory.ComputerFactory"/>
    
    <!-- 2、创建computer -->
    <!-- factory-bean引用工厂对象 -->
    <bean id="computer" factory-bean="factory"  factory-method="createComputer"/>

四.Spring核心容器给对象注入的三种方式
1.构造方法注入(有参构造)

public class Student {
    
    private int id;
    private String name;
    private String sex;
    
    public Student(int id, String name, String  sex) {
        super();
        this.id = id;
        this.name = name;
        this.sex = sex;
    }
    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" +  name + ", sex=" + sex + "]";
    }
}
    配置spring.xml
<bean id="student"  class="com.youzhong.entity.Student">
        <constructor-arg index="0" value="66"/>
        <constructor-arg index="1" value="张梓"/>
        <constructor-arg index="2" value="男"/>
    </bean>
    测试类
public static void main(String[] args) {
        //1、解析spring.xml,创建核心容器
        ApplicationContext ac = new  ClassPathXmlApplicationContext("spring.xml");
        
        //2、从容器中取出student
        Object bean = ac.getBean("student");
        
        System.out.println(bean);
    }

2.set方法注入(最常用)

public class Student {
    
    private int id;
    private String name;
    private String sex;
    
    public void setDd(int id) {
        this.id = id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" +  name + ", sex=" + sex + "]";
    }
}
    配置spring.xml
<bean id="student"  class="com.youzhong.entity.Student">
        <!-- property标签使用set方法注入,name需要和set方法名匹配 -->
        <property name="dd" value="88"/>
        <property name="name" value="张梓"/>
        <property name="sex" value="男"/>
    </bean>
    测试
public static void main(String[] args) {
        //1、解析spring.xml,创建核心容器
        ApplicationContext ac = new  ClassPathXmlApplicationContext("spring.xml");
        
        //2、从容器中取出student
        Object bean = ac.getBean("student");
        
        System.out.println(bean);
    }

    可以注入复杂的类型
public class Student {
    
    private int id;
    private String name;
    private String sex;
    
    private Student girlFriend;//女朋友
    private Student[] boyFriends;//男朋友们
    private List<String> laoxiang;//老乡们
    private Set<String> sheyou;//舍友们
    private Map<String,Double> money;//存款
    private Properties chengji;//成绩
    配置spring.xml
<bean id="student"  class="com.youzhong.entity.Student">
        <!-- property标签使用set方法注入,name需要和set方法名匹配 -->
        <property name="id" value="88"/>
        <property name="name" value="张梓"/>
        <property name="sex" value="男"/>
        <property name="girlFriend" ref="s2"/>
        <property name="boyFriends">
            <array>
                <ref bean="s3"/>
                <ref bean="s4"/>
            </array>
        </property>
        <property name="laoxiang">
            <list>
                <value>张三</value>
                <value>张三丰</value>
            </list>
        </property>
        <property name="sheyou">
            <set>
                <value>王龙</value>
                <value>王龙</value>
                <value>小胖</value>
            </set>
        </property>
        <property name="money">
            <map>
                <entry key="ICBC"  value="200.1"/>
                <entry key="ABC"  value="1200.1"/>
                <entry key="CBC"  value="3200.1"/>
            </map>
        </property>
        <property name="chengji">
            <props>
                <prop key="java基础">90</prop>
                <prop key="struts2">60</prop>
                <prop key="spring">30</prop>
            </props>
        </property>
    </bean>
    
    <bean id="s2"  class="com.youzhong.entity.Student">
        <property name="name" value="刘瑶"/>
    </bean>
    
    <bean id="s3"  class="com.youzhong.entity.Student">
        <property name="name" value="杨语"/>
    </bean>
    
    <bean id="s4"  class="com.youzhong.entity.Student">
        <property name="name" value="康子硕"/>
    </bean>

3.注解注入(很常用)
@Autowired 自动绑定
@Resource 资源

上面两个注解可以添加在属性上面,如果添加了此注解,容器必须为此属性注入,容器会找一个bean进行赋值,如果找不到就直接报错。
注解注入一般用在对象类型的属性上,不在int,String等基本类型上使用。

注意:注解注入需要添加spring-aop.jar包,配置注解开关。

 球队Team类
public class Team {
    private int id;
    private String name;
    
    @Override
    public String toString() {
        return "Team [id=" + id + ", name=" +  name + "]";
    }
    
}
    球员Player类
public class Player {
    private int id;
    private String name;
    //@Resource
    @Autowired
    private Team team;
    
    @Override
    public String toString() {
        return "Player [id=" + id + ", name=" +  name + ", team=" + team + "]";
    }
    
}
    配置spring.xml
<!-- 注解开关:扫描@Autowired等注解  -->
    <context:annotation-config/>
    
    <bean id="player"  class="com.youzhong.entity.Player"/>
    
    <bean id="team"  class="com.youzhong.entity.Team"/>
    测试
public static void main(String[] args) {
        //1、解析spring.xml,创建核心容器
        ApplicationContext ac = new  ClassPathXmlApplicationContext("spring2.xml");
        
        //2、从容器中取出student
        Object bean = ac.getBean("player");
        
        System.out.println(bean);
    }

@Autowired与@Resource的区别:
1、@Autowired是spring框架提供的注解,@Resource是jdk提供的注解。
2、@Autowired根据类型绑定
@Resource先根据名字绑定,再根据类型绑定。

五.Spring核心容器的其他功能
一、bean的作用域(scope):
常用的两个作用域:singleton 单例的 , prototype 原型的(多例的)
单例:容器只创建一个实例。
多例:容器会创建多个实例。
默认创建的bean是单例的。

1、单例bean的配置:
<bean id="shanzhu"  class="com.youzhong.entity.ShanZhu"/>

<bean id="shanzhu"  class="com.youzhong.entity.ShanZhu"  scope="singleton"/>

    2、多例的bean配置:
<bean id="shanzhu"  class="com.youzhong.entity.ShanZhu"  scope="prototype"/>

二、注解扫描管理bean
有4个注解可以扫描管理bean:
@Controller , @Service , @Repository , @Component
控制器 服务,业务 仓库,存储 组件
上面4个注解是加在类上的。

1、在spring.xml中配置注解扫描的包
<!-- 组件扫描,bask-package配置基包,扫描基包及其所有子包中的类 -->
    <context:component-scan  base-package="com.youzhong.entity"/>
    2、在类上添加注解
@Controller
public class ShanZhu {
}
注解扫描管理bean时,创建的bean的默认id是类名小驼峰。
    3、测试
public static void main(String[] args) {
        //1、解析spring.xml,创建核心容器
        ApplicationContext ac = new  ClassPathXmlApplicationContext("spring.xml");
        
        //2、从容器中取出student
        Object bean = ac.getBean("shanzhu");
        
        System.out.println(bean);
    }

注意:
1.注解扫描创建的bean,作用域(scope)默认是单例的。
注解扫描创建多例的bean,需要添加一个注解:

@Component
@Scope("prototype")
public class Banana {
}
  1. 注解扫描管理的bean,默认id是类名小驼峰。
    也可以自定义bean的id:
@Component("orange")
@Scope("prototype")
public class Banana {
}
  1. @Component(“orange”)
    上面注解的配置,"orange"默认赋给了注解的value属性,注解必须有value属性。
@Table(name="t_user")
name=是不能省略的,如果省略,"t_user"默认赋给value属性,@Table没有value属性。

 如果要给注解赋多个属性值,属性名都不能省略。

三、bean的生命周期

1、Apple类
public class Apple {
    //初始化
    public void aaaa() {
        System.out.println("先洗洗");
    }
    
    //销毁
    public void destroy() {
        System.out.println("扔到垃圾桶");
    }
}
    2、配置spring.xml
<!-- init-method配置初始化方法,destroy-method配置销毁方法 -->
    <bean id="apple"  class="com.youzhong.entity.Apple"
        init-method="aaaa"  destroy-method="destroy"
    />
    3、测试
public static void main(String[] args) {
        //1、解析spring.xml,创建核心容器
        ClassPathXmlApplicationContext ac = new  ClassPathXmlApplicationContext("spring.xml");
        
        //2、从容器中取出student
        //Object bean1 = ac.getBean("apple");
        
        //关闭容器
        ac.close();
    }

小知识: 核心容器会在创建出来bean之后,立即对其初始化,调用init-method配置的方法。
当容器销毁时,也会销毁所有的bean,之前会调用destroy-method配置的方法。

一般的bean不会管理生命周期,复杂的bean才会管理生命周期。

四、懒加载
核心容器会立即把单例的bean创建出来,多例的bean不会立即创建。
懒加载是对于单例的bean进行设置的。

复杂的bean,可能用不到的bean,才需要懒加载。

五、depends-on 依赖
比如容器创建两个bean,apple和banana

上述配置,容器会先创建apple,再创建banana。 如果希望先创建banana,后创建apple,控制bean的创建顺序。
<bean id="banana"  class="com.youzhong.entity.Banana"/>

六、autowire 自动绑定
autowire使用byName或byType自动绑定时,需要调用set方法。
1、开发Player,Team类

> public class Player {
>     private String name;

        private Team team;
        
        public void setTeam(Team team) {
            this.team = team;
        }
        @Override
        public String toString() {
            return "Player [name=" + name + ",  team=" + team + "]";
        }
        
    }
    public class Team {
    }
2、配置spring.xml
<!-- autowire叫做自动绑定byName是根据名字byType是根据类型 -->
<bean id="player"  class="com.youzhong.entity.Player"  autowire="byName"/>

<bean id="xxx"  class="com.youzhong.entity.Team"/>
3、测试
public static void main(String[] args) {
        //1、解析spring.xml,创建核心容器
```
  ApplicationContext ac = new  ClassPathXmlApplicationContext("spring.xml");
```
        
        Object bean = ac.getBean("player");
        
        System.out.println(bean);
    }

    autowire配置default时,会使用根标签<beans>中的default-autowire的设置。

<!-- autowire叫做自动绑定byName是根据名字byType是根据类型 -->
<bean id="player"  class="com.youzhong.entity.Player"  autowire="default"/>

<bean id="xxx"  class="com.youzhong.entity.Team"/>

七、多个spring.xml互相导入

还可以使用如下方式解析多个配置文件
ApplicationContext ac = new  ClassPathXmlApplicationContext("spring.xml","spring2.xml");
ApplicationContext ac = new  ClassPathXmlApplicationContext("spring*.xml");

八、核心容器接口
常用的接口有两个:BeanFactory , ApplicationContext
BeanFactory是spring框架内部使用的,只提供了管理bean的功能。
ApplicationContext 是框架外部使用的,它是BeanFactory的孙子接口,扩展了BeanFactory的功能,增加了一些企业级的应用。
Player bean = ac.getBean(“player”, Player.class); // 可以返回准确类型的bean