Spring 框架 IOC 与 DI 的总结

一:Spring并天下

1:Spring帝国:

①:Spring崛起

什么是Spring:

        源于Rod Johnson在其著作《Expert one on one J2EE design and development》中阐述的部分

理念和原型的衍生而来.Spring是一个轻量级的DI/AOP容器的开源框架,致力于构建轻量级的JavaEE应用,简化应用

开发,本身涵盖了传统应用开发还拓展到移动端,大数据领域.

什么是容器(Container):

        从程序设计角度看就是装对象的对象,因为存在放入,拿出等操作,所以容器还是要管理对象的生命周期,如

Tomcat就是Service和JSP的容器.

        Spring提供了JavaEE每一层的解决方案(full stack) .Spring其实就是全栈式框架.

    ![Spring与SpringMVC的框架整合](https://img-blog.csdn.net/20180404200433463?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

②:Spring的优势:

Spring除了不能帮我们写业务逻辑,其余的几乎什么都能帮助我们简化开发.

    ①:Spring能帮我们低侵入/低耦合地根据配置文件创建及相关对象之间的依赖关系.

    ②:Spring面向切面编程能帮我们无耦合的实现日志记录,性能统计,安全控制等.

    ③:Spring能非常简单的且强大的声明式事务管理.

    ④:Spring提供了与第三方数据访问框架(如:Hibemate,JPA)无缝集成,且自己也提供了一套JDBC模板来方便数据库访问.

    ⑤:Spring提供与第三方Web(如Struts1/2,JSF)框架无缝集成,且自己也提供了一套Spring MVC框架来方便Web层搭建.

    ⑥:Spring能方便的与Java Mail,任务调度,缓存框架等技术整合,降低开发难度.

③:Spring帝国

Spring主要产品:

        Spring FrameWork:

        Spring帝国之核心,其他Spring其他产品都是基于Spring框架而来.

        Spring Boot:

        Spring Boot 是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用

        的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而是开发人员不在需要定义样板化的配置.

        Spring Cloud:Spring cloud微服务框架,为开发者提供了在分布式系统(配置管理,服务发现,熔断,路由,微代理,

        控制总线,一次性token,全居锁,leader选举,分布式session,集群状态)中快速构建的工具,使用Spring Cloud的

        开发者可以快速的启动服务或构建应用,同时能够快速和云平台资源进行对接.

        Spring Cloud Data Flow: 

        Spring Cloud Data Flow简化了专注于数据流处理的应用程序的开发和部署.通过

        SpringBoot启动应用,采用Spring Cloud Stream,Spring Cloud Task完成微服务构建.

        官网的推荐组合:Spring Boot + Spring Cloud + Spring Cloud Data Flow

        ![Spring的其他主要项目版图](https://img-blog.csdn.net/20180404203728808?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

④:Spring基石

    ![Spring基石,了解一下就行,框住的是我们需要学习的](https://img-blog.csdn.net/20180404204632103?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

⑤:Spring框架包

Spring框架包包含两大部分:

1:spring-framework-5.X.RELEASE:Spring核心组件(必须).

        docs: Spring开发,帮助文档.

        libs: Spring 核心组件的,jar包,源代码,文档.

        schema: Spring配置文件的schema约束文件.

2:spring-framework-3.0.5.RELEASE-dependencies:

        Spring依赖的第三方组件(根据需要拷贝),包含了各大开源组织提供的依赖jar,比如日志库,AOP联盟库,连接池库等.

        建议使用meve来下载jar包,不需要拷贝jar包了.

⑥:STS工具

    Eclipse: STS工具  Spring Tool Suite基于Eclipse的开发工具.

    IDEA:  后面会录制一套IDEA的视频.

2:Spring基础

①:Ioc和DI思想

IoC: Inversion of Control(控制反转):读作"翻转控制",更好理解,不是什么技术,而是一种设计思想,

        好比于MVC.就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理.

    正控:若调用者需要使用某个对象,其自身就得负责该对象及该对象所依赖对象的创建和组装.

    反控:调用者只管负责从Spring容器中获取需要使用的对象,不关心对象的创建过程,也不关心该对象依赖对象的

        创建以及依赖关系的组装,也就是把创建对象的控制权翻转给了Spring框架.

DI: Dependency Injection (依赖注入)从字面上分析: IoC:指将对象的创建权,翻转给了Spring容器:  DI:指Spring

        创建对象的过程中,将对象依赖属性(常量,对象,集合)通过配置设置值给该对象.

IoC 从字面意义上很难体现出谁来维护对象之间的关系,Martin  Fowler提出一个新的概念--DI,更明确描述了"被注入对象(service对象)

    依赖IoC容器来配置依赖对象(DAO对象)".

②:HelloWord程序

依赖jar:

    spring-beans-版本.RELEASE.jar

    spring-core-版本.RELEASE.jar

    报错再添加:

    com.springsource.org.apache.commons.logging-1版本.jar
开发jar包

    1:准备jar包

    2:开发HelloWorld程序

    3:在applicationContext.xml中完成配置(如何获取xsd声明)

    4:启动Spring容器

    5:从容器中获取指定名称的bean

    6:调用bean的方法
什么是BeanFactory:

    BeanFactorySpring最古老的接口,表示Spring IoC容器--生产bean对象的工厂,负责配置,创建和管理bean

什么是Bean:Spring Ioc容器管理的对象称之为bean.

Spring Ioc容器如何知道哪些是它管理的对象:

    此时需要配置文件:Spring Ioc容器通过读取配置文件中的配置元数据,通过元数据对应用中的各个对象进行实例化及装配.

元数据的配置有三种方式(后讲):

    1:XML-based configuration

    2:Annotation-based configuration

    3:Java-bean configuration

Spring IoC管理bean的原理:

    1:通过Resource对象加载配置文件

    2:解析配置文件,得到指定名称的bean

    3:解析bean元素,id作为bean的名字,class用于反射得到bean实例:

      注意:此时,bean类必须存在一个无参数构造器(和访问权限无关);

    4:调用getBean方法的时候,从容器中返回对象实例;

    结论:就是把代码从JAVA文件中转移到XML中.

③:getBean方法的三种签名

    //使用Spring框架之后
    @Test
    public void test2() throws Exception {
        HelloWorld world = null;
        //---------------------------------
        //1:从classpath路径去寻找资源问价,创建资源对象
        Resource resource = new ClassPathResource("applicationContext.xml");
        //2:根据资源对象,创建Spring IoC容器对象 
        BeanFactory factory = new XmlBeanFactory(resource);
        //3:从Spring IoC容器中获取指定名称(helllo world)对象
        //签名一:Object getBean(String beanName);//根据bean对象在容器中的名称来取
        //world = (HelloWorld) factory.getBean("HelloWorld");
        //签名二: T getBean(Class requiredType)//按照指定的类型去寻找bean对象
        //world = factory.getBean(HelloWorld.class);
        //签名三: T getBean(String name, @Nullable Class requiredType)根据bean的类型+ID名称去寻找,推荐的
        world = factory.getBean("HelloWorld",HelloWorld.class);
        //---------------------------------
        world.sayHello();
    }

④:Eclipse提示XML语法

XML需要导入schema约束,约束指向网络路径:

    方式一:连网后,自动缓存路径文件到本地,提供提示功能;

    方式二:无连网,需要配置xsd schema文件位置(操作如下图);

            ①:到解压spring/schemas/beans/spring-bean.xsd.

            ②:选择schema location方式.

            ③:复制网络路径 http://www.springframework.org/schema/beans/spring-beans.xsd

⑤:Spring基本配置

id="helloWorld" class="cn.wolfcode.hello.HelloWorld"/>

    nameid 以后只需要用id属性就行,表示的意思一样,但是name元素可以用空格隔开不同的名字

""/>元素

    在开发中,随着应用规模的增加,系统中元素配置的数量也会增加,导致applicationContext.xml配置

    文件变得非常臃肿,为了提高其可读性,我们可以将一个applicationContext.xml文件分解成多个配置文件,

    然后在applicationContext.xml文件中包含其他配置文件即可.

    语法如下: "classpath:cn/wolfcode/hello/hello.xml"/>

    使用import元素注意:

        1:默认情况下:从classpath的根路径寻找.

        2:可以使用前缀来定位文件的基础位置:

            ①:[classpath:] 后面的文件从classpath路径开始找(推荐);

            ②:[file]:后面的文件使用文件系统的路径开始找;

        注意:只有当框架中实现了Resource接口才能够识别上诉的前缀标识符.

⑥:Spring测试框架

测试依赖:

        Spring-test-版本.RELEASE.jar

        Spring-context-版本.RELEASE.jar

        Spring-aop-版本.RELEASE.jar

        Spring-expression-版本.RELEASE.jar
    //使用Junit4的测试案例
    //运行Spring的jUnit4
    @RunWith(SpringJUnit4ClassRunner.class)
    //上下文配置对象,寻找配置文件的
    //@ContextConfiguration("classpath:cn/wolfcode/spring_test/springtext.xml")
    @ContextConfiguration//默认从测试了路径找    测试类名-context.xml文件
    public class SpringTestTest {

        //表示自动按照类型从Spring容器中找到bean对象,并设置给该字段
        @Autowired
        private SomeBean bean; 

        @Test
        public void test() throws Exception {
            bean.doWork();
        }
    }
    //使用Junit5方式的测试
    @SpringJUnitConfig
    public class SpringTestTest{

        @Autowired
        private SomeBean bean;

        @Test
        void testName(){
            bean.doWork();
        }
    }

二: 帝国之剑 IoC

1:IoC

①:IOC容器

    1:SpringIoC容器(Contaner):

      BeanFactory:  Spring 最底层的接口,只提供了IoC功能,负责创建,组装,管理Bean,在应用中,一般不使

                   用BeanFactory,而推荐使用ApplicationContext(应用上下文).

       ApplicationContext:接口继承了BeanFactory,除此之外还提供AOP集成,国际化处理,事件传播,统一资源加载等功能.

    2:Bean的创建时机(此时不使用Spring Test)::BeanFactory需要等到获取某一个bean的时候才会创建bean--延迟初始化.

        ②:ApplicationContext在启动Spring容器的时候就会创建所有的bean(Web应用建议).

        bean属性中的lazy-init="true"也可以延迟初始化,也可以设置到到schema上面的default-lazy-init="true"
    /**
        结论:BeanFactory有延迟初始化的特点,在创建Spring容器的时候,不会立马去创建容器中管理的Bean对象
            而是要等到从容器中去获取对象的时候,才去创建对象.

     */
    //使用BeanFactory
    @Test
    public void testBeanFactory() throws Exception {
        Resource resource = new ClassPathResource("cn/wolfcode/container/ContainerTest-Context.xml");
        BeanFactory factory = new XmlBeanFactory(resource);
        System.out.println("====================");
        Person person = factory.getBean("person",Person.class);
        System.out.println(person);
    }


    /**
    结论:在创建Spring容器的时候,就会把容器中管理的bean马上初始化,而不会等到获取bean的时候才去初始化.

     */
    //使用ApplicationContext
    @Test
    public void test2() throws Exception {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/wolfcode/container/ContainerTest-Context.xml");
        System.out.println("============================");
        Person person = ctx.getBean("person",Person.class);
        System.out.println(person);
    }

②:bean实例化方式:

    ①:构造器实例化(无参数构造器),最标准,使用最多.       (使用比较多)

    ②:静态工厂方法实例化:解决系统遗留问题

    ③:实例工厂方法实例化:解决系统遗留问题

    ④:实现FactoyrBean接口实例化:实例工厂变种,如集成MyBatis框架使用: (使用比较多)

        org.mybatis.spring.SqlSessionFactoryBean
    
    <bean id="cat1" class="cn.wolfcode.createbean._01_constructor.Cat1"/>

    
    <bean id="cat2" class="cn.wolfcode.createbean._02_static_factory.Cat2Factory" 
    factory-method="createInstance"/>

       
    <bean id="cat3" class="cn.wolfcode.createbean._03_instance_factory.Cat3Factory"/>
    <bean id="getcat3" factory-bean="cat3" factory-method="createInstance"/>

    
    <bean id="dat4" class="cn.wolfcode.createbean._04_factory_bean.Cat4Factory">
        <property name="username" value="你好">property>
    bean>

③:bean的作用域:

    在Spring容器中是指其创建的Bean对象相对于其他Bean对象的请求可见范围

    "" scope="作用域"/>

    singleton: 单例,在Spring IoC容器中仅存在一个Bean实例 (默认的scope)

    proptotype: 多例,每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行new XxxBean();不会再容器启动时创建对象

    request: 用于web开发,将Bean放入request范围,request.setAttribute("xxx")在调用一个request获得同一个Bean

    session:用于web开发,将Bean放入Session范围,在同一个 Session获得同一个Bean

    globalSession:一般用于Porlet应用环境,分布式系统存在全局session概念(单点登录),如果不是porlet环境.

    globalSession 等同于Session

    Spring5开始出现:websocket, globalSession作废.

    在开发中主要使用  scope="singleton"  scope="prototype"

    总结: 对于Struts1中的Action使用request, Struts2中的Action使用prototype类型,其他使用singleton

④:bean初始化和销毁

    init-method: 定义初始化方法,在构造器执行之后,立马执行

    destroy-method: 定义销毁之前的方法,在销毁执行之前,调用

    scope: 设置为"prototype" 不是 单例设计模式, 他不知道你啥时候调用完,所以就不关闭资源  考虑资源来之不易,不易轻易释放

    "ds" class="cn.wolfcode.lifecycle.MyDataSource" scope="singleton"
    init-method="open" destroy-method="close"/>

    此方法在Spring测试类可用

    如果使用ApplicationContext来创建对象,就得手动关闭资源

    @Test
    public void testName1() throws Exception {
        @Cleanup
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("cn/wolfcode/lifecycle/App-Context.xml");
        MyDataSource ds = ctx.getBean("ds",MyDataSource.class);
        ds.doWork();
    }

    三种关闭资源方法:最后加  ds.close();     @Clearup;      ctx.registerShutdownHook();

⑤:bean的实例化过程(生命周期)

bean的生命周期: bean从出身--消亡直接的整个过程

BeanFactory:         延迟初始化特点

ApplicationContext:  在启动Spring容器的时候,就会去创建bean对象

    ![bean的生命周期](https://img-blog.csdn.net/2018040512541723?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

    ![bean的生命周期2](https://img-blog.csdn.net/20180405125513373?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

    ![bean的生命周期3](https://img-blog.csdn.net/20180405132714642?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

2: DI

①:通过XML配置装配

DI:Dependency Injection(依赖注入)

    从字面上分析:IoC:指对象的创建权,反转给了Spring容器;

DI:Spring创建对象的过程中,将对象依赖属性(常量,对象,集合)通过配置设值给该对象.

什么是注入操作?      setter方法    构造器

注入值的类型:

            1):常量值(简单类型):value元素

            2):对象 :   ref元素

            3):集合 :   对应集合类型元素

通过XML配置装配(不推荐)

    id="dog" class="" autowire="byType" />  autowire: byName  byType  constructor  no

②:setter注入

    注入常量  注入对象  注入集合  跟上面注入方法一样
    
    <bean id="employee" class="cn.wolfcode.di_setter.Employee1">
        <property name="name" value="will">property>
        <property name="age" value="17">property>
        <property name="salary" value="5000">property>
    bean> 
    
    

    
    <bean id="cat1" class="cn.wolfcode.di_setter.Cat1">bean>
    <bean id="person" class="cn.wolfcode.di_setter.Person1" >
        <property name="c1" ref="cat1">property>
    bean>

    
    <bean id="collectionBean1" class="cn.wolfcode.di_setter.CollectionBean1">
        <property name="set">
            <set>
                <value>set1value>
                <value>set2value>
            set>
        property>
        <property name="list">
            <list>
                <value>list1value>
                <value>list2value>
            list>
        property>
        <property name="array">
            <array>
                <value>array1value>
                <value>array2value>
            array>
        property>
        <property name="map">
            <map>
                <entry key="key1" value="value1"/>
                <entry key="key2" value="value2"/>
            map>
        property>
        
        <property name="prop">
            <value>
                p1=v1
                p2=v2
                p3=v3
            value>
        property>
    bean>

③:构造器注入

把上面的property换成constructor-arg  即可
<bean id="person2" class="cn.wolfcode.di_constructor.Person2" >
    <constructor-arg name="c2">
            <bean class="cn.wolfcode.di_constructor.Cat2"/>
    constructor-arg>
bean>

④:bean元素的继承

多个bean元素共同配置的抽取,实则是bean配置的拷贝,和Java的继承不同.

    
    <bean id="base" abstract="true">
        <property name="name" value="will">property>
        <property name="age" value="19">property>
    bean>

    
    <bean id="someBean1" class="cn.wolfcode.bean_tag_inheritance.SomeBean1" parent="base">
        <property name="weight" value="500">property>
    bean> 

    
    <bean id="someBean2" class="cn.wolfcode.bean_tag_inheritance.SomeBean2" parent="base">
        <property name="age" value="99">property>
        <property name="color" value="业楼">property>
    bean>

⑤:配置数据库连接池

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration
    public class App {

        @Autowired
        private DataSource ds;

        @Test
        public void testName() throws Exception {
          /*ds = new DruidDataSource();
            ds.setDriverClassName("com.mysql.jdbc.Driver");
            ds.setUrl("jdbc:mysql://localhost:3306/springdemo");
            ds.setUsername("root");
            ds.setPassword("111111");
            ds.setInitialSize(2);*/

            @Cleanup
            Connection conn = ds.getConnection();
            @Cleanup
            PreparedStatement ps = conn.prepareStatement("SELECT * FROM student");
            @Cleanup
            ResultSet rs = ps.executeQuery();
            while(rs.next()){
                System.out.print(rs.getLong("id")+",");
                System.out.print(rs.getString("name")+",");
                System.out.println(rs.getInt("age")+",");
            }
        }
    }

⑥:property-placeholder

    
     
        <context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/>


    
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
        init-method="init" destroy-method="close" >
        <property name="driverClassName" value="${jdbc.driverClassName}">property>
        <property name="url" value="${jdbc.url}">property>
        <property name="username" value="${jdbc.username}">property>
        <property name="password" value="${jdbc.password}">property>
        <property name="initialSize" value="${jdbc.initialSize}">property>
    bean>

⑦:模拟用户注册的例子

查看我的Eclipse代码,利用xml配置的方式回顾了IoC跟DI.

domain

@Setter@ToString@Getter
public class User {
    private Long id;
    private String name;
    private int age;
}

dao

public interface IUserDAO {

    void save(User u);
}

impl

public class IUserDAOImpl implements IUserDAO{

    @Setter
    private DataSource ds;

    @SneakyThrows
    public void save(User u){
        System.out.println("保存操作");
        @Cleanup
        Connection conn = ds.getConnection();
        String sql = "INSERT INTO user (name,age) values (?,?)";
        @Cleanup
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setString(1,u.getName());
        ps.setInt(2, u.getAge());
        ps.executeUpdate();
    }
}

service

public interface IUserService {

    void register(User user);
}

impl

public class UserServiceImpl implements IUserService{

    private IUserDAO dao;

    public void setDao(IUserDAO dao) {
        this.dao = dao;
    }

    @SneakyThrows
    public void register(User user){
        System.out.println("注册操作");
        dao.save(user);
    }
}

action

//模拟Struts2的Action/SpringMVC的Controller
public class UserAction {

    @Setter
    private IUserService service;

    public String execute() throws Exception{
        System.out.println("注册请求");
        service.register(new User());
        return "success";
    }
}

app

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {

    @Autowired
    private UserAction userAction;

    @Test
    public void testRegister() throws Exception {
        userAction.execute();
    }
}

app-Context.xml

        
        <context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/>
        
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" 
        init-method="init" destroy-method="close">
            <property name="driverClassName" value="${jdbc.driverClassName}">property>
            <property name="url" value="${jdbc.url}">property>
            <property name="username" value="${jdbc.username}">property>
            <property name="password" value="${jdbc.password}">property>
            <property name="initialSize" value="${jdbc.initialSize}">property>
        bean>

        
        <bean id="userdao" class="cn.wolfcode.register.dao.impl.IUserDAOImpl">
            <property name="ds" ref="dataSource">property>
        bean>

        
        <bean id="UserService" class="cn.wolfcode.register.service.impl.UserServiceImpl">
            <property name="dao" ref="userdao">property>
        bean>

        
        <bean id="userAction" class="cn.wolfcode.register.action.UserAction" scope="prototype">
            <property name="service" ref="UserService" >property>
        bean>

3:使用注解配置

①:DI注解

Autowired和Qualifier注解

Spring规范提供

    1:可以让Spring自动的把属性的对象找出来,并注入到对象.

    2:可以贴在字段或者setter方法上面

    3:可以同时注入多个对象

        @Autowired
        public void setter(OtherBean otherBean,OtherBean other2){}

    4:可以注入一些Spring内置的重要对象,比如BeanFactory,ApplicationContext,ServiceContext等;

    5:默认情况下Autiwrired注解必须要能找到对应的对象,否则报错.

        通过required=false来避免这个问题:@Autowired(required=false)

    6:第三方程序:Spring3.0之前,需要手动配置Autowired注解的解析程序:

        在Web开发中必须配置

    7:Autowired注解寻找bean的方法:

        1):首先按照依赖对象的类型找,如果找到,就是用setter或者字段直接注入

        2):如果Spring上下文中找到多个匹配类型,再按照名字去找,如果没有 匹配报错;

        3):可以通过使用@Qualifier("name")标签来规定依赖对象按照bean的id和类型的组合方式去找;

Resource

DI注解:

        Spring官方:  Autowired

        JavaEE规范:  Resource

共同点:  都需要配置DI注解解析器:  

不同点:    Resource注解必须要能找到对应的对象,否则报错.

        Resource注解首先按照名字去找,如果找到,就使用setter或者字段注入;

        如果按照名字找不到,再按照类型去找,但如果找到多个匹配类型,报错;

        Resource可以直接使用name属性指定bean的名称(@Resource(name="名字"));但是

            如果指定的name,就只能按照name去找如果找不到,就不再按照类型去找

Value

注入:
        常量类型:   value       Value

        对象类型:   ref         Autowired/Resource

        @Value("${service.port}")
        private int port;

        
        <context:property-placeholder location="classpath:db.properties,classpath:server.properties"/>  

②:IoC注解

Component注解和其stereotype注解

    //注解配置:@Component
    @Component("myDataSource")//组件如果不写value属性值,此时bean的id默认是类型首字母小写;
    public class MyDataSource {

    }

    
    <context:component-scan base-package="cn.wolfcode.ioc"/>
bean组件版型:四个组件的功能是相同的,只是用于标注不同类型的组件.

    @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注.

    @Repository用于标注数据访问组件,即DAO组件.

    @Service用于标注业务层组件.

    @Controller用于标注控制层组件(如struts中的Ation,SpringMVCController).

    他们几个的功能跟component功能其实是一模一样的.优先使用下面3种注解,当不属于其他组件再使用component

③:Scope 和 PostConstruc 以及 PreDestroy 注解

@PostConstruct用于贴在初始化方法上

@PreDestroy用于贴在销毁方法上

    @Component
    @Scope("singleton")
    public class SomeBean {

        public SomeBean(){
            System.out.println("构建SomeBean对象");
        }

        @PostConstruct//构建对象之后
        public void open(){
            System.out.println("初始化方法");
        }

        @PreDestroy//销毁之前
        public void close(){
            System.out.println("销毁前扫尾方法");
        }

        public void doWork(){
            System.out.println("工作");
        }
    }

    之后记得写IoC注解解析器
    package="cn.wolfcode.lifecycle"/>

④:使用注解完成注册案例

注意:

    使用注解并不能完全取代XML的配置

    比如配置连接池DruiDataSource,我们就不能到这个类中去贴注解.

    JavaConfig + 注解

    @setter注解贴在字段上面仅仅是为我们生成一个Setter方法,本身不能完成注入操作.

    @Autowired注解贴在字段上面,自动从Spring 容器中去找到匹配的对象,并设置给该字段.

IoCDI其实是一个东西:

    IoC:字面上,更多强调的是Spring帮我们创建对象.

    DI:字面上,Spring不仅帮我们创建对象,还要为该对象设置依赖的数据.

    最后学会用XML与注解完成注册案例配置

domain

@Setter@ToString@Getter
public class User {
    private Long id;
    private String name;
    private int age;
}

dao

public interface IUserDAO {

    void save(User u);
}

impl

@Repository
public class IUserDAOImpl implements IUserDAO{

    @Autowired
    private DataSource ds;

    @SneakyThrows
    public void save(User u){
        System.out.println("保存操作");
        @Cleanup
        Connection conn = ds.getConnection();
        String sql = "INSERT INTO user (name,age) values (?,?)";
        @Cleanup
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setString(1,u.getName());
        ps.setInt(2, u.getAge());
        ps.executeUpdate();
    }
}

service

public interface IUserService {

    void register(User user);
}

impl

@Service
public class UserServiceImpl implements IUserService{

    @Autowired
    private IUserDAO dao;

    @SneakyThrows
    public void register(User user) {
        System.out.println("注册操作");
        dao.save(user);
    }
}

action

@Component//变现层
public class UserAction {

    @Autowired
    private IUserService service;

    public String execute() throws Exception{
        System.out.println("注册请求");
        service.register(new User());
        return "success";
    }
}

APP

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {

    @Autowired
    private UserAction userAction;

    @Test
    public void testRegister() throws Exception {
        userAction.execute();
    }
}

APP-context.xml


<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
        http://www.springframework.org/schema/context/spring-context.xsd
        " >

        
        <context:annotation-config/>
        
        <context:component-scan base-package="cn.wolfcode"/>

        
        <context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/>
        
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" 
        init-method="init" destroy-method="close">
            <property name="driverClassName" value="${jdbc.driverClassName}">property>
            <property name="url" value="${jdbc.url}">property>
            <property name="username" value="${jdbc.username}">property>
            <property name="password" value="${jdbc.password}">property>
            <property name="initialSize" value="${jdbc.initialSize}">property>
        bean>
beans>

你可能感兴趣的:(Spring)