• Spring IoC


    录:

    1、spring介绍
    2、Spring IoC helloworld
    3、依赖注入DI,setter方法注入,构造方法注入
    4、bean的实例化方式(三种)
    5、Spring 容器类
    6、基于xml装配bean---作用域
    7、属性注入
    8、bean之间的关系
    9、p命令空间和SpEL
    10、Spring容器中bean的生命周期
    11、装配Bean--基于注解Annotation

    1、spring介绍    <--返回目录

        * 什么是spring:
            - Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,
              因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003 年兴起的一个轻量级的Java 开发框架,
              由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。
            - 轻量级:与EJB对比,依赖资源少,消耗的资源少。
            - 分层: 一站式,每一个层都提供的解决方案
                web层:struts,spring-MVC
                service层:spring
                dao层:hibernate,mybatis , jdbcTemplate  --> spring-data
                
        * Spring的核心:控制反转(IoC,Inverse of Control)和面向切面编程(AOP,)
        * IoC意思:将创建对象的控制权反转给了spring,换一句话说就是,以后对象全部由spring创建
        
        * spring的优点
            - 方便解耦,简化开发 (高内聚低耦合)
                Spring就是一个大工厂(容器),可以将所有对象创建和依赖关系维护,交给Spring管理
                spring工厂是用于生成bean
            - AOP编程的支持
                Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
            - 声明式事务的支持
                只需要通过配置就可以完成对事务的管理,而无需手动编程
            - 方便程序的测试
                Spring对Junit4支持,可以通过注解方便地测试Spring程序
            - 方便集成各种优秀框架
                Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持
            - 降低JavaEE API的使用难度
                Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低

      * spring 体系

    2、Spring IoC helloworld    <--返回目录

      定义 bean

    public class HelloWorld {
        public void sayHi() {
            System.out.println("hello,你好!!!");
        }
    }

      beans.xml

    <?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">
        
        <!-- 装配bean -->
        <bean id="HelloWorldBeanId" class="com.oy.entity.HelloWorld"/>
        
    </beans>

      测试类

    package com.oy.test;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.oy.entity.HelloWorld;
    
    /**
     * HelloWorld演示:
     *         1)编写JavaBean类
     *         2)配置<bean>
     *         3)初始化Spring IoC容器
     *         4)获取bean实例
     * 
     * @author oy
     * @version 1.0
     * @date 2018年12月29日
     * @time 上午1:25:43
     */
    class HelloWorldTest {
    
        @Test
        public void test() {
            // 初始化Spring IoC容器
            ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
            // 根据name获取bean实例
            HelloWorld hw = (HelloWorld)ctx.getBean("HelloWorldBeanId");
            hw.sayHi();
        }
    
    }

    3、依赖注入DI,setter方法注入,构造方法注入    <--返回目录

        * DI:Dependency Injection , 依赖注入
        * 什么叫依赖?
            - is a:是一个,继承;子类继承父类==>子类is a 父类
            - has a:有一个,成员变量,依赖。
                public B {
                    private A a;  //B类依赖A类
                }
        * 注入:通过setter方法进行另一个对象实例设置
                public B {
                    private A a;  //B类依赖A类
                    
                    public A setA(A a) {
                        this.a = a;     //注入
                    }
                }


        * 例如:
            class BookServiceImpl{
                //之前开发:接口 = 实现类  (service和dao耦合)
                //private BookDao bookDao = new BookDaoImpl();
                //spring之后 (解耦:service实现类使用dao接口,不知道具体的实现类,后面使用setter注入实现类)
                private BookDao bookDao;
                setter方法
            }
            
            模拟spring执行过程
            创建service实例:BookService bookService = new BookServiceImpl()    -->IoC  <bean>
            创建dao实例:BookDao bookDao = new BookDaoImple()                    -->IoC
            将dao设置给service:bookService.setBookDao(BookDao);                -->DI   <property>

      People

    package com.oy.entity;
    
    /**
     * @author oy
     * @version 1.0
     * @date 2018年12月29日
     * @time 上午7:32:23
     */
    public class People {
        private Integer id;
        private String name;
        private Integer age;
        
        public People() {
            System.out.println("调用People的无参构造。。。");
        }
        
        public People(Integer id, String name, Integer age) {
            super();
            System.out.println("调用People的有参构造。。。");
            this.id = id;
            this.name = name;
            this.age = age;
        }
        // getXxx 和 setXxx
    }

      PeopleTest

    package com.oy.test;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.oy.entity.People;
    
    /**
     * 2种依赖注入方法:
     *  1.setter方法注入
     *  2.构造方法注入
     *  
     * @author oy
     * @version 1.0
     * @date 2018年12月29日
     * @time 上午7:37:57
     */
    public class PeopleTest {
        @SuppressWarnings("resource")
        @Test
        public void test1() {
            // 初始化Spring IoC容器
            ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
            
            // 根据name获取bean实例
            // =====测试依赖注入:setter方法注入=====
            People p = (People)ctx.getBean("people");
            System.out.println(p.getId() + "---" + p.getName() + "---" + p.getAge());
            
            // =====测试依赖注入:构造方法注入=====
            // 通过索引
            People p2 = (People)ctx.getBean("people2");
            System.out.println(p2.getId() + "---" + p2.getName() + "---" + p2.getAge());
            // 通过类型
            People p3 = (People)ctx.getBean("people3");
            System.out.println(p3.getId() + "---" + p3.getName() + "---" + p3.getAge());
            // 通过索引和类型
            People p4 = (People)ctx.getBean("people4");
            System.out.println(p4.getId() + "---" + p4.getName() + "---" + p4.getAge());
        }
    }

      beans.xml

    <?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">
        
        <!-- ==========依赖注入:使用setter方法========== -->
        <!-- 装配bean过程:
            IoC容器初始化时,调用People类的无参构造创建bean实例,
            然后调用People类的setter方法给属性注入值
        -->
        <bean id="people" class="com.oy.entity.People">
            <!-- 依赖注入:使用setter方法注入 -->
            <property name="id" value="1"></property>
            <property name="name" value="张三1"></property>
            <property name="age" value="15"></property>
        </bean>
        
        
        <!-- ==========依赖注入:使用构造方法========== -->
        <!-- 装配bean过程:
            IoC容器初始化时,调用People类的有参构造创建bean实例
        -->
        <bean id="people2" class="com.oy.entity.People">
            <!-- 依赖注入:使用有参构造注入 -->
            <!-- 通过索引 -->
            <constructor-arg index="0" value="2"></constructor-arg>
            <constructor-arg index="1" value="李四2"></constructor-arg>
            <constructor-arg index="2" value="25"></constructor-arg>
        </bean>
        
        <bean id="people3" class="com.oy.entity.People">
            <!-- 依赖注入:使用有参构造注入 -->
            <!-- 通过类型 -->
            <constructor-arg type="Integer" value="3"></constructor-arg>
            <constructor-arg type="String" value="李四3"></constructor-arg>
            <constructor-arg type="Integer" value="35"></constructor-arg>
        </bean>
    
        <bean id="people4" class="com.oy.entity.People">
            <!-- 依赖注入:使用有参构造注入 -->
            <!-- 通过类型和索引 -->
            <constructor-arg index="0" type="Integer" value="4"></constructor-arg>
            <constructor-arg index="1" type="String" value="李四4"></constructor-arg>
            <constructor-arg index="2" type="Integer" value="45"></constructor-arg>
        </bean>
        
    </beans>

    4、bean的实例化方式(三种)    <--返回目录

      方式一:默认构造 <bean id="" class="">  必须提供默认构造

      方式二:静态工厂

      方式三:实例工厂

       PeopleFactory

    package com.oy.entity;
    
    /**
     * 定义了一个非静态工厂
     * @author oy
     * @version 1.0
     * @date 2018年12月29日
     * @time 上午8:10:25
     */
    
    public class PeopleFactory {
    
        public People createPeople() {
            People p = new People();
            p.setId(5);
            p.setName("李四5");
            p.setAge(55);
            return p;
        }
    }

      PeopleStaticFactory

    package com.oy.entity;
    
    /**
     * 静态工厂
     * @author oy
     * @version 1.0
     * @date 2018年12月29日
     * @time 上午8:25:21
     */
    
    public class PeopleStaticFactory {
        public static People createPeople() {
            People p = new People();
            p.setId(6);
            p.setName("李四6");
            p.setAge(66);
            return p;
        }
    }

      测试类

    package com.oy.test;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.oy.entity.People;
    
    /**
     * bean的实例化方式 :
     *     1.无参构造
     *         <bean id="" class=""> 或 使用setter方法注入属性时都是调用无参构造来实例化bean
     *  2.有参构造
     *      使用构造方法注入属性时调用有参构造
     *  3.非静态工厂
     *  4.静态工厂
     */
    public class PeopleTest {
        @SuppressWarnings("resource")
        @Test
        public void test1() {
            // 初始化Spring IoC容器
            ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
            
            // =====测试bean的实例化方式:非静态工厂=====
            People p5 = (People)ctx.getBean("people5");
            System.out.println(p5.getId() + "---" + p5.getName() + "---" + p5.getAge());
            
            // =====测试bean的实例化方式:静态工厂=====
            People p6 = (People)ctx.getBean("people6");
            System.out.println(p6.getId() + "---" + p6.getName() + "---" + p6.getAge());
            
        }
    }

      beans.xml

    <?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">
        
        <!-- ==========bean的实例化方式:使用非静态工厂========== -->
        <bean id="peopleFactory" class="com.oy.entity.PeopleFactory"/>
        <!-- 装配bean过程:
            IoC容器初始化时,调用factory-bean实例的createPeople()方法
        -->
        <bean id="people5" factory-bean="peopleFactory" factory-method="createPeople"/>
          
          <!-- ==========bean的实例化方式:使用静态工厂========== -->
          <!-- 装配bean过程:
            IoC容器初始化时,调用静态工厂的createPeople()方法
        -->
          <bean id="people6" class="com.oy.entity.PeopleStaticFactory" factory-method="createPeople"/>
          
    </beans>

    5、Spring 容器类    <--返回目录

        * api整体了解,之后不使用,在学习过程需要使用,所以了解即可。
        * BeanFactory :这是一个工厂,用于生成任意bean。
            - 【采取延迟加载,第一次getBean时才会初始化Bean】
        * ApplicationContext:是BeanFactory的子接口,功能更强大。
            - (国际化处理、事件传递、Bean自动装配、各种不同应用层的Context实现)。
            - 【当配置文件被加载,就进行对象实例化】
        * ClassPathXmlApplicationContext 用于加载classpath(类路径、src)下的xml
            加载xml运行时位置 --> /WEB-INF/classes/*.xml
        * FileSystemXmlApplicationContext 用于加载指定盘符下的xml
            一般加载xml运行时位置 --> /WEB-INF/*.xml
            也就是说如果xml文件放在/WEB-INF/*.xml,可以使用FileSystemXmlApplicationContext
                通过java web ServletContext.getRealPath() 获得具体盘符

    6、基于xml装配bean---作用域    <--返回目录

        * 作用域:用于确定spring创建bean实例个数
        * 取值:
            - singleton 单例,默认值。
            - prototype 多例,每执行一次getBean将获得一个实例。例如:struts整合spring,配置action多例。
        * 如何配置:<bean id="" class=""  scope="singleton|prototype">

    7、属性注入    <--返回目录

    public class Dog {
        private String name;
        public Dog() {
            System.out.println("调用Dog的无参构造。。。");
        }
        // getXxx和setXxx
    }
    public class People {
        private Integer id;
        private String name;
        private Integer age;
        private Dog dog;
        private List<String> hobbies = new ArrayList<String>();
        private Map<String, Object> map = new HashMap<String, Object>();
        private Properties props = new Properties();
        
        public People() {
            System.out.println("调用People的无参构造。。。");
        }
        
        public People(Integer id, String name, Integer age) {
            super();
            System.out.println("调用People的有参构造。。。");
            this.id = id;
            this.name = name;
            this.age = age;
        }
        // getXxx和setXxx
    }

      beans.xml

    <?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">
    
        <!-- 依赖注入:属性是基本数据类型 -->
        <bean id="people" class="com.oy.entity.People">
            <property name="id" value="1"></property>
            <property name="name" value="张三1"></property>
            <property name="age" value="15"></property>
        </bean>
    
        <!-- 依赖注入:属性是bean,注入外部bean -->
          <bean id="people2" class="com.oy.entity.People">
            <property name="id" value="1"></property>
            <property name="name" value="张三1"></property>
            <property name="age" value="15"></property>
            <property name="dog" ref="dog"></property>
        </bean>
        <!-- dog配置在people2后面也是可以的 -->
        <bean id="dog" class="com.oy.entity.Dog">
            <property name="name" value="jack"></property>
        </bean>
        
        <!-- 依赖注入:属性是bean,注入内部bean -->
          <bean id="people3" class="com.oy.entity.People">
            <property name="id" value="1"></property>
            <property name="name" value="张三1"></property>
            <property name="age" value="15"></property>
            <property name="dog">
                <bean class="com.oy.entity.Dog">
                    <property name="name" value="tom"></property>
                </bean>
            </property>
        </bean>
        
        <!-- 依赖注入:属性是bean,注入null -->
          <bean id="people4" class="com.oy.entity.People">
            <property name="id" value="1"></property>
            <property name="name" value="张三1"></property>
            <property name="age" value="15"></property>
            <property name="dog">
                <null></null>
            </property>
        </bean>
        
        <!-- 依赖注入:属性是List集合 -->
          <bean id="people5" class="com.oy.entity.People">
            <property name="id" value="1"></property>
            <property name="name" value="张三1"></property>
            <property name="age" value="15"></property>
            <property name="hobbies">
                <list>
                    <value>吃饭</value>
                    <value>睡觉</value>
                    <value>打豆豆</value>
                </list>
            </property>
        </bean>
        
        <!-- 依赖注入:属性是Map集合 -->
          <bean id="people6" class="com.oy.entity.People">
            <property name="id" value="1"></property>
            <property name="name" value="张三1"></property>
            <property name="age" value="15"></property>
            <property name="map">
                <map>
                    <entry key="key1" value="value1"/>
                    <entry key="key2" value="value2"/>
                </map>
            </property>
        </bean>
        
        <!-- 依赖注入:属性是Properties -->
          <bean id="people7" class="com.oy.entity.People">
            <property name="id" value="1"></property>
            <property name="name" value="张三1"></property>
            <property name="age" value="15"></property>
            <property name="props">
                <props>
                    <prop key="username">张三</prop>
                    <prop key="password">123</prop>
                </props>
            </property>
        </bean>
        
    </beans>

      测试类

    package com.oy.test;
    
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.oy.entity.People;
    
    /**
     * 测试依赖注入
     * 属性的类型分为:
     *     1.基本数据类型
     *     2.bean    
     *         通过ref引用注入外部bean
     *         注入内部bean
     *         注入null
     *  3.List集合  (数组Array类似)
     *  4.Map集合
     *  5.Properties类型
     * 
     * @author oy
     * @version 1.0
     * @date 2018年12月29日
     * @time 上午8:57:22
     */
    class PeopleTest {
    
        ApplicationContext ctx = null;
                
        @BeforeEach
        void setUp() throws Exception {
            ctx = new ClassPathXmlApplicationContext("beans.xml");
        }
    
        /**
         * 依赖注入:属性是基本数据类型
         */
        @Test
        void test1() {
            People p = (People)ctx.getBean("people");
            System.out.println(p.getId() + "---" + p.getName() + "---" + p.getAge());
        }
    
        /**
         * 依赖注入:属性是bean,注入外部bean
         */
        @Test
        void test2() {
            People p2 = (People)ctx.getBean("people2");
            System.out.println(p2.getId() + "---" + p2.getName() + "---" 
                    + p2.getAge() + "---" + p2.getDog().getName());
        }
        
        /**
         * 依赖注入:属性是bean,注入内部bean
         */
        @Test
        void test3() {
            People p3 = (People)ctx.getBean("people3");
            System.out.println(p3.getId() + "---" + p3.getName() + "---" 
                    + p3.getAge() + "---" + p3.getDog().getName());
        }
        
        /**
         * 依赖注入:属性是bean,注入null
         */
        @Test
        void test4() {
            People p4 = (People)ctx.getBean("people4");
            System.out.println(p4.getId() + "---" + p4.getName() + "---" 
                    + p4.getAge() + "---" + p4.getDog());
        }
        
        /**
         * 依赖注入:属性是List集合
         */
        @Test
        void test5() {
            People p5 = (People)ctx.getBean("people5");
            System.out.println(p5.getId() + "---" + p5.getName() + "---" 
                    + p5.getAge() + "---" + p5.getHobbies());
        }
        
        /**
         * 依赖注入:属性是Map集合
         */
        @Test
        void test6() {
            People p6 = (People)ctx.getBean("people6");
            System.out.println(p6.getId() + "---" + p6.getName() + "---" 
                    + p6.getAge() + "---" + p6.getMap());
        }
        
        /**
         * 依赖注入:属性是Properties
         */
        @Test
        void test7() {
            People p7 = (People)ctx.getBean("people7");
            System.out.println(p7.getId() + "---" + p7.getName() + "---" + p7.getAge() + "---" 
            + p7.getProps().getProperty("username") + p7.getProps().getProperty("password"));
        }
    }

    8、bean之间的关系    <--返回目录

    public class People {
        private Integer id;
        private String name;
        private Integer age;
        private String className;
        
        public People() {
            System.out.println("调用People的无参构造。。。");
        }
        // getXxx和setXxx
        @Override
        public String toString() {
            return "People [id=" + id + ", name=" + name + ", age=" + age + ", className=" + className + "]";
        }
    }
    public class User {
        private Integer id;
        private String username;
        private String password;
        
        public User() {
            System.out.println("调用User的无参构造。。。");
        }
        // getXxx和setXxx
        @Override
        public String toString() {
            return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
        }
    
    }

      beans.xml

    <?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">
    
        <!-- bean之间的关系:继承 -->
        <bean id="peopleParent" class="com.oy.entity.People" abstract="true">
            <property name="age" value="18"></property>
            <property name="className" value="高三1班"></property>
        </bean>
        
        <bean id="zhangsan" parent="peopleParent" depends-on="user">
            <property name="id" value="1"></property>
            <property name="name" value="zhangsan"></property>
            <property name="age" value="19"></property>
        </bean>
        
        <bean id="lisi" parent="peopleParent">
            <property name="id" value="2"></property>
            <property name="name" value="lisi"></property>
        </bean>
        
        <bean id="user" class="com.oy.entity.User">
            <property name="id" value="1"></property>
            <property name="username" value="zhangsan"></property>
            <property name="password" value="123"></property>
        </bean>
        
    </beans>

      测试类

    package com.oy.test;
    
    import org.junit.Before;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.oy.entity.People;
    import com.oy.entity.User;
    
    /**
     * bean之间的关系:
     *         1.继承
     *             定义抽象bean:<bean id="parent" class="" abstract="true">
     *             继承:<bean id="" parent="parent">
     *             
     *         2.依赖
     *             <bean id="bean1" class="" depends-on="bean2"/>
     *             bean1依赖bean2,bean2必须要在bean1之前初始化
     * 
     *         3.引用  ref
     *             <bean id="" class="">
     *                 <property name="dog" ref="dog"/> 
     *             </bean>
     * 
     * @author oy
     * @version 1.0
     * @date 2018年12月29日
     * @time 上午10:51:26
     */
    public class PeopleTest {
        ApplicationContext ctx = null;
        @Before
        public void before() {
            ctx = new ClassPathXmlApplicationContext("beans.xml");
        }
    
        /**
         * bean之间的关系:继承
         */
        @Test
        public void test1() {
            People zhangsan = (People)ctx.getBean("zhangsan");
            System.out.println(zhangsan);
            
            People lisi = (People)ctx.getBean("lisi");
            System.out.println(lisi);
        }
        
        /**
         * bean之间的关系:依赖
         * Spring IoC容器初始化bean是按配置文件从上到下
         * 需求:假设初始化<bean id="zhangsan">这个bean之前,必须先初始化<bean id="user">,
         *      便认为<bean id="zhangsan">依赖<bean id="user">
         * 配置:<bean id="zhangsan" depends-on="user">
         */
        @Test
        public void test2() {
            People zhangsan = (People)ctx.getBean("zhangsan");
            System.out.println(zhangsan);
            
            People lisi = (People)ctx.getBean("lisi");
            System.out.println(lisi);
            
            User user = (User)ctx.getBean("user");
            System.out.println(user);
            
        }
    }

    9、p命令空间和SpEL    <--返回目录

    public class Address {
        private Integer id;
        private String addrName;
        
        public String fun() {
            return "abc";
        }
        // getXxx和setXxx
    }    
    public class Customer {
        private String cname = "jack";
        private Double pi;
        private Address address;
        private String addressName;
        private String str;
        // getXxx和setXxx
    }
    public class Student {
        private Integer id;
        private String name;
        private Integer age;
        private Address address;
        // getXxx和setXxx
    }

      beans.xml

    <?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:p="http://www.springframework.org/schema/p"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="student1" class="com.oy.entity.Student">
            <property name="id" value="1"></property>
            <property name="name" value="张三"></property>
            <property name="age" value="10"></property>
            <property name="address" ref="address"></property>
        </bean>
        
        <!-- 使用P命名空间 -->
        <bean id="student2" class="com.oy.entity.Student" 
            p:id="2" p:name="张三2" p:age="20" p:address-ref="address">
        </bean>
        
        <bean id="address" class="com.oy.entity.Address"
            p:id="1" p:addrName="深圳">
        </bean>
        
        <!-- 使用SpEL -->
        <bean id="customer" class="com.oy.entity.Customer">
            <!-- <property name="cname" value="#{'李四'}"></property> -->
            <!-- 如果customer.cname?为null,不再调用后面方法 -->
            <property name="cname" value="#{customer.cname?.toUpperCase()}"></property>
            <property name="pi" value="#{T(Math).PI}"></property>
            <property name="address" value="#{address}"></property>
            <property name="addressName" value="#{address.addrName}"></property>
            <property name="str" value="#{address.fun()}"></property>
        </bean>
    </beans>

      测试类

    package com.oy.test;
    
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.oy.entity.Customer;
    import com.oy.entity.Student;
    
    /**
     * P命名空间
     *         1)P命名空间使用前提,必须添加命名空间。
     *         2)对"setter方法注入"进行简化,替换<property name="属性名" value/ref="属性值">,
     *         在<bean p:属性名="普通值"  p:属性名-ref="引用值">
     * 
     * SpEL:
     *         1)对<property>进行统一编程,所有的内容都使用value
     *         2)<property name="" value="#{表达式}">
     *             #{123}、#{'jack'} : 数字、字符串
     *             #{beanId} :另一个bean引用
     *            #{beanId.propName}    :操作数据
     *            #{beanId.toString()}    :执行方法
     *            #{T(类).静态字段|静态方法}    :静态方法或字段
     * 
     * @author oy
     * @version 1.0
     * @date 2018年12月30日
     * @time 上午12:15:58
     */
    public class StudentTest {
        ClassPathXmlApplicationContext ctx = null;
    
        @Before
        public void setUp() throws Exception {
            ctx = new ClassPathXmlApplicationContext("beans.xml");
        }
    
        @After
        public void tearDown() throws Exception {
            ctx.close();
        }
    
        /**
         * 测试P命名空间
         */
        @Test
        public void test() {
            Student stu1 = (Student)ctx.getBean("student1");
            System.out.println(stu1);
            
            Student stu2 = (Student)ctx.getBean("student2");
            System.out.println(stu2);
        }
        
        /**
         * 测试SpEL
         */
        @Test
        public void test2() {
            Customer customer = (Customer)ctx.getBean("customer");
            System.out.println(customer.getCname());
            System.out.println(customer.getPi());
            System.out.println(customer.getAddress());
            System.out.println(customer.getAddressName());
            System.out.println(customer.getStr());
        }
    }

    10、Spring容器中bean的生命周期    <--返回目录

        * 1.bean的初始化方法和销毁方法:
        *       容器加载配置文件初始化后,将调用People的无参构造进行bean实例化,
        *       然后调用bean实例的初始化方法  init-method="myInit"。
        *       什么时候调用销毁方法   destroy-method="myDestroy"?容器关闭时,且bean是单例的。
        * 2.BeanPostProcessor接口: 后处理Bean
        *   spring 提供一种机制,只要实现此接口BeanPostProcessor,并将实现类提供给spring容器,
        *      spring容器将自动执行,在容器每个bean的初始化方法前执行before(),在容器每个bean初始化方法后执行after()。
        * 3.模拟Spring IoC实例化bean的过程,即bean的生命周期:

    A a =new A();    --> 调用无参构造创建对象
    
    a = B.before(a); --> 将a的实例对象传递给后处理bean,可以生成代理对象并返回。
    a.init();          --> 调用bean的初始化方法
    a = B.after(a);
    
    a.addUser();      //生成代理对象,目的是在目标方法前后执行(例如:开启事务、提交事务、性能监控)
    
    a.destroy()

       Spring容器中bean的生命周期

    1、instantiate bean对象实例化
    2、populate properties 封装属性
    3、如果Bean实现BeanNameAware 执行 setBeanName
    4、如果Bean实现BeanFactoryAware 或者 ApplicationContextAware 设置工厂 setBeanFactory 或者上下文对象 setApplicationContext
    5、如果存在类实现 BeanPostProcessor(后处理Bean) ,执行postProcessBeforeInitialization
    6、如果Bean实现InitializingBean 执行 afterPropertiesSet 
    7、用<bean init-method="myInit"> 指定初始化方法 myInit
    8、如果存在类实现 BeanPostProcessor(处理Bean),执行postProcessAfterInitialization
    9、执行业务处理(执行目标方法)
    10、如果Bean实现 DisposableBean 执行 destroy
    11、调用<bean destroy-method="myDestroy"> 指定销毁方法 myDestroy

       IPeople

    public interface IPeople {
        public void add();
        public void delete();
    }

      People

    public class People implements IPeople{
        private Integer id;
        private String name;
        private Integer age;
        private String className;
        
        public People() {
            System.out.println();
            System.out.println("==========调用People无参构造==========");
        }
        
        public void myInit() {
            System.out.println("调用People初始化方法。。。");
        }
        
        public void myDestroy() {
            System.out.println("调用People销毁方法。。。");
        }
        
        @Override
        public void add() {
            System.out.println("调用People目标方法:add()。。。");
            long sum = 0;
            for (int j = 0; j < 1000; j++) {
                sum = 0;
                for (long i = 0; i < 100000; i++) {
                    sum += i;
                }
            }
            
            System.out.println(sum);
        }
        
        @Override
        public void delete() {
            System.out.println("调用People目标方法:delete()。。。");
            long sum = 0;
            for (int j = 0; j < 1000; j++) {
                sum = 0;
                for (long i = 0; i < 100000; i++) {
                    sum += i;
                }
            }
            System.out.println(sum);
        }
        // getXxx和setXxx
    }

      IUserService

    public interface IUserService {
        public void add();
        public void delete();
    }

      UserServiceImpl

    public class UserServiceImpl implements IUserService{
        private Integer id;
        private String username;
        private String password;
        
        public UserServiceImpl() {
            System.out.println();
            System.out.println("==========调用UserServiceImpl无参构造==========");
        }
        
        public void myInit() {
            System.out.println("调用UserServiceImpl初始化方法。。。");
        }
        
        public void myDestroy() {
            System.out.println("调用UserServiceImpl销毁方法。。。");
        }
        
        @Override
        public void add() {
            System.out.println("调用UserServiceImpl目标方法:add()。。。");
        }
        
        @Override
        public void delete() {
            System.out.println("调用UserServiceImpl目标方法:delete()。。。");
        }
        // getXxx和setXxx
    }

      StudentService

    public interface StudentService {
        void add();
    }

      StudentServiceImpl

    package com.oy.entity;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.BeanNameAware;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    
    public class StudentServiceImpl implements StudentService,BeanNameAware,ApplicationContextAware {
        private String beanName;
        private ApplicationContext applicationContext;
        
        // 无参构造
        public StudentServiceImpl() {
            System.out.println();
            System.out.println("==========调用StudentServiceImpl无参构造==========");
        }
        
        // 初始化方法
        public void myInit() {
            System.out.println("调用StudentServiceImpl初始化方法。。。");
        }
        
        // 销毁方法
        public void myDestroy() {
            System.out.println("调用StudentServiceImpl销毁方法。。。");
        }
        
        // 目标方法
        public void add() {
            System.out.println("调用StudentServiceImpl目标方法:add()。。。");
        }
    
        /**
         * 在bean实例化过程中,调用此方法,将beanName注入给bean实例,
         * 那么可以在此方法外面定义一个属性beanName,将注入的beanName保存起来,
         * 从而其他方法也可以用。
         */
        @Override
        public void setBeanName(String beanName) {
            this.beanName = beanName;
            System.out.println("给StudentServiceImpl注入属性值beanName:" + this.beanName);
        }
    
        /**
         * 给StudentServiceImpl注入属性值applicationContext。
         * 打印applicationContext类型名称
         */
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext = applicationContext;
            System.out.println("给StudentServiceImpl注入属性值applicationContext:" + this.applicationContext.getClass().getName());
        }
    
    }

      Spring后处理 BeanPostProcessor 的实现类 BeanPostProcessorImpl

    package com.oy.entity;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    
    public class BeanPostProcessorImpl implements BeanPostProcessor {
        
        public BeanPostProcessorImpl() {
            System.out.println();
            System.out.println("==========调用BeanPostProcessorImpl无参构造==========");
        }
        
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("前处理方法,beanName为:" + beanName);
            return bean;
        }
    
        /**
         * 参数bean:目标对象,即被代理的bean对象
         * 参数beanName:被代理对象的名字,即bean的id属性值
         */
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("后处理方法,bean的类型为:" + bean.getClass().getName());
            
            // 通过beanName过滤,对不同的bean进行处理
            if ("userService".equals(beanName)) {
                // 生成jdk代理
                return Proxy.newProxyInstance(
                        BeanPostProcessorImpl.class.getClassLoader(), 
                        bean.getClass().getInterfaces(), 
                        new InvocationHandler() {
                            
                            @Override
                            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                System.out.println("===开启事务===");
                                Object obj = method.invoke(bean, args);
                                System.out.println("===提交事务===");
                                return obj;
                            }
                            
                        });
            } else if ("people".equals(beanName)) {
                // 生成jdk代理
                return Proxy.newProxyInstance(
                        BeanPostProcessorImpl.class.getClassLoader(), 
                        bean.getClass().getInterfaces(), 
                        new InvocationHandler() {
                            
                            @Override
                            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                
                                //System.out.println(proxy.getClass().getName()); // com.sun.proxy.$Proxy6
                                
                                long start = System.currentTimeMillis();
                                Object obj = method.invoke(bean, args);
                                long time = System.currentTimeMillis() - start;
                                
                                System.out.println("方法" + method.getName() + "()共耗时:" + time + "毫秒");
                                return obj;
                            }
                            
                        });
            } else {
                // 直接返回bean,不生成代理对象
                return bean;
            }      
        }
    }

      DisPosableBeanImpl

    public class DisPosableBeanImpl implements DisposableBean {
        
        public DisPosableBeanImpl() {
            System.out.println();
            System.out.println("==========调用DisPosableBeanImpl无参构造==========");
        }
    
        @Override
        public void destroy() throws Exception {
            System.out.println("");
            System.out.println("");
            System.out.println("Spring IoC容器关闭。。。");
        }
    
    }

      beans.xml

    <?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">
    
        <bean id="people" class="com.oy.entity.People" init-method="myInit" destroy-method="myDestroy"></bean>
        
        <bean id="userService" class="com.oy.entity.UserServiceImpl" init-method="myInit" destroy-method="myDestroy"></bean>
        
        <bean id="stuServiceId" class="com.oy.entity.StudentServiceImpl" init-method="myInit" destroy-method="myDestroy"></bean>
        
        
        
        
        <!-- 将后处理BeanPostProcessor接口的实现类注册到Spring容器 -->
        <!-- spring将首先初始化该bean,与在xml配置的位置无关 -->
        <bean class="com.oy.entity.BeanPostProcessorImpl"/>
        
        <!-- 将DisPosableBean接口的实现注册到Spring容器 -->
        <bean id="disPosableBeanImpl" class="com.oy.entity.DisPosableBeanImpl"/>
        
    </beans>

       测试类

    package com.oy.test;
    
    import org.junit.Before;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.oy.entity.IPeople;
    import com.oy.entity.IUserService;
    
    /**
     * bean的生命周期:
     *     1.bean的初始化方法和销毁方法
     *      <bean id="" class="" init-method="" destroy-method=""/>
     *     2.BeanPostProcessor接口: 后处理Bean
     *  
     * @author oy
     * @version 1.0
     * @date 2018年12月29日
     * @time 上午10:51:26
     */
    public class PeopleTest {
        ApplicationContext ctx = null;
        @Before
        public void before() {
            ctx = new ClassPathXmlApplicationContext("beans.xml");
        }
    
        /**
         * 1.bean的初始化方法和销毁方法:
         *       容器加载配置文件初始化后,将调用People的无参构造进行bean实例化,
         *       然后调用bean实例的初始化方法  init-method="myInit"。
         *       什么时候调用销毁方法   destroy-method="myDestroy"?容器关闭时,且bean是单例的。
         * 2.BeanPostProcessor接口: 后处理Bean
         * spring 提供一种机制,只要实现此接口BeanPostProcessor,并将实现类提供给spring容器,
         *      spring容器将自动执行,在容器每个bean的初始化方法前执行before(),在容器每个bean初始化方法后执行after()。
         * 3.模拟Spring IoC实例化bean的过程,即bean的生命周期:
             A a =new A();    --> 调用无参构造创建对象
             
             a = B.before(a); --> 将a的实例对象传递给后处理bean,可以生成代理对象并返回。
             a.init();          --> 调用bean的初始化方法
             a = B.after(a);
            
             a.addUser();      //生成代理对象,目的是在目标方法前后执行(例如:开启事务、提交事务、性能监控)
            
             a.destroy()
         * @throws Exception 
         */
        @Test
        public void test1() throws Exception {
            System.out.println("=======容器初始化完毕=======");
            IPeople p = (IPeople)ctx.getBean("people");
            
            //目标方法
            p.add();
            p.delete();
            
            // 容器关闭时,调用销毁方法   destroy-method="myDestroy",要保证bean是单例的。
            //ctx.getClass().getMethod("close").invoke(ctx);
            // 事实上,close()方法是ClassPathXmlApplicationContext类中提供的
            // 使用多态(子类对象指向父类引用),不能直接调用子类特有的方法
            // 向下强转
            ((ClassPathXmlApplicationContext)ctx).close();
        }
        
        @Test
        public void test2() throws Exception {
            System.out.println("=======容器初始化完毕=======");
            IUserService u = (IUserService)ctx.getBean("userService");
            
            //目标方法
            u.add();
            u.delete();
                    
            // 容器关闭时,调用销毁方法   destroy-method="myDestroy",要保证bean是单例的。
            ((ClassPathXmlApplicationContext)ctx).close();
        }
        
    }
    package com.oy.test;
    
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.oy.entity.StudentService;
    
    /**
     * @author oy
     * @version 1.0
     * @date 2019年1月1日
     * @time 上午3:26:32
     */
    public class StudentTest {
    
        ClassPathXmlApplicationContext ctx = null;
        @Before
        public void setUp() throws Exception {
            ctx = new ClassPathXmlApplicationContext("beans.xml");
        }
    
        @After
        public void tearDown() throws Exception {
            System.out.println();
            System.out.println("===========销毁IoC容器===========");
            ctx.close();
        }
    
        /* 测试结果:
            ==========调用BeanPostProcessorImpl无参构造==========
    
            ==========调用DisPosableBeanImpl无参构造==========
            前处理方法,beanName为:disPosableBeanImpl
            后处理方法,bean的类型为:com.oy.entity.DisPosableBeanImpl
            
            ==========调用People无参构造==========
            前处理方法,beanName为:people
            调用People初始化方法。。。
            后处理方法,bean的类型为:com.oy.entity.People
            
            ==========调用UserServiceImpl无参构造==========
            前处理方法,beanName为:userService
            调用UserServiceImpl初始化方法。。。
            后处理方法,bean的类型为:com.oy.entity.UserServiceImpl
            
            ==========调用StudentServiceImpl无参构造==========
            给StudentServiceImpl注入属性值beanName:stuServiceId
            给StudentServiceImpl注入属性值applicationContext:org.springframework.context.support.ClassPathXmlApplicationContext
            前处理方法,beanName为:stuServiceId
            调用StudentServiceImpl初始化方法。。。
            后处理方法,bean的类型为:com.oy.entity.StudentServiceImpl
            调用StudentServiceImpl目标方法:add()。。。
            
            ===========销毁IoC容器===========
            调用StudentServiceImpl销毁方法。。。
            调用UserServiceImpl销毁方法。。。
            调用People销毁方法。。。
            
    
            Spring IoC容器关闭。。。
         */
        @Test
        public void test() {
            StudentService studentService = (StudentService)ctx.getBean("stuServiceId");
            studentService.add();
        }
    
    }

    11、装配Bean--基于注解Annotation    <--返回目录

      注解使用前提:添加schema命名空间,让spring扫描含有注解的类

    <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"><!-- 组件扫描,扫描含有注解的类 base-package:指定包 -->
        <context:component-scan base-package="com.oy"></context:component-scan>
    </beans>


      @Component取代<bean class=""/>
           @Component("userDaoid")取代<bean id="userDaoId" class="UserDaoImpl"/>   
           在UserDaoImpl类定义中添加注解@Component("userDaoId")===>这就相当于在配置文件中写了<bean id="userDaoId" class="UserDaoImpl"/>

        * web开发,提供3个@Component注解衍生注解(功能一样)取代<bean class="">
            @Repository :dao层
            @Service:service层
            @Controller:web层
        
        * 依赖注入,给私有字段设置,也可以给setter方法设置
            普通值:@Value("")
            引用值:
                方式1:按照【类型】注入
                    @Autowired
                方式2:按照【名称】注入1
                    @Autowired
                    @Qualifier("名称")
                方式3:按照【名称】注入2
                    @Resource[("名称")]
        * 注意:            
            @Resource不写名称,就是根据【类型】注入
            @Resource是JDK提供的,jdk1.5没有
            @Autowired是由spring提供的
            
        * 生命周期
            初始化:@PostConstruct
            销毁:    @PreDestroy
            
        * 作用域
            @Scope("prototype") 多例

  • 相关阅读:
    Java工作流引擎全局变量的介绍
    Java工作流系统-CCBPM如何自动升级?
    驰骋工作流系统-Java共工作流引擎配置定时任务
    那些年下过的大雨
    移动端APP列表点透事件处理方法
    关于React中状态保存的研究
    几个关于js数组方法reduce的经典片段
    关于React组件之间如何优雅地传值的探讨
    模拟制作网易云音乐(AudioContext)
    移动端效果之IndexList
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/13756802.html
Copyright © 2020-2023  润新知