SSM-Spring(一)-简介、IoC、依赖注入

简介

  1. Spring框架可以算是Java开发中最常用的框架,功能非常强大
    1. 最早之前java的三大框架是SSH(Struts(网络层)、Spring、Hibernate(dao层))
    2. 现在流行的java三大框架SSM(SpringMVC、Spring、MyBatis)
    3. 官方网站:https://spring.io/
    4. https://spring.io/projects/spring-framework
    5. 官网标语:Spring makes Java simple、modern、productive…
  2. Spring框架的几个核心概念
    1. IoC:In version of Control, 控制反转
    2. DI:Dependency Injection,依赖注入
    3. AOP:Aspect Oriented Programming, 面向切面编程
  3. 当前使用的版本是5.2.8
    1. 核心参考文档
    2. API文档

Spring的下载

  1. jar包、文档下载:https://repo.spring.io/
    1. 点击左边菜单第二个图标进入:Artifact Repository Browser
    2. 列表中找到libs-release-local点击箭头展开列表
    3. 点击org展开,点击springframework展开
    4. 找到Spring找到5.2.8.RELEASE点击展开
    5. 找到spring-5.2.8.RELEASE-dist.zip,点击,然后点击右边的download即可,里面包含了离线文档
  2. 源码下载:https://github.com/spring-projects/spring-framework

IoC容器

IoC的引入

1.基础的项目结构:servlet层、service层、dao层

//servlet层
public class PersonServlet {
    //使用service层
    private  PersonService service = new PersonServiceImpl();
    //模拟网络请求调用:删除一条数据
    public void remove() {
        service.remove(1);
    }
    //模拟客户端调用网络接口
    public static void main(String[] args) {
        PersonServlet servlet = new PersonServlet();
        servlet.remove();
    }
}
    
//service层
//接口
public interface PersonService {
    boolean remove(Integer id);
}
//impl
public class PersonServiceImpl implements PersonService {
    //使用dao层
    private PersonDao dao = new PersonDaoImpl();
    @Override
    public boolean remove(Integer id) {
        return dao.remove(id);
    }
}
    
//dao层
//接口
public interface PersonDao {
    boolean remove(Integer id);
}
//impl
public class PersonDaoImpl implements PersonDao {
    @Override
    public boolean remove(Integer id) {
        System.out.println("PersonDaoImpl ------ remove: " + id);
        return false;
    }
}
  1. 存在问题
    1. 耦合严重:PersonServlet依赖于PersonServiceImpl,PersonServiceImpl依赖于PersonDaoImpl,一旦某个环境的类型改变,其他依赖必须也要改变,即servlet依赖于service层,service层依赖于dao层
    2. 如何解耦? —工厂设计模式

2.工厂设计模式来解耦

  1. 新增一个工厂类:com.zh.factory.PersonFactory;

     public class PersonFactory {
         public static PersonService getService (){
             return  new PersonServiceImpl();
             //return  new PersonServiceImpl2();
         }
         public static PersonDao getDao(){
             return new PersonDaoImpl();
         }
     }
    
  2. 将servlet、service中的依赖分别替换如下

     //PersonServlet中替换
     private  PersonService service = PersonFactory.getService();
     //PersonServiceImpl中替换
     private PersonDao dao = PersonFactory.getDao();
    
  3. 这样一来,如果修改service、dao的实现类,那么就只需要在工厂类PersonFactory中修改了
  4. 那么是否也可以将PersonFactory解耦呢?就是修改service、dao实现不需要修改PersonFactory?—配置文件

3.配置文件解耦

  1. service、dao实现类的类名放到配置文件中去,PersonFactory只加载配置文件

     //resources文件中添加配置文件factory.properties
     personService=com.zh.service.impl.PersonServiceImpl
     personDao=com.zh.dao.impl.PersonDaoImpl
    
  2. 改造PersonFactory类工厂代码如下:

     public class PersonFactory {
         private static Properties properties;
         static {
             try (InputStream is = PersonFactory.class.getClassLoader().getResourceAsStream("factory.properties")) {
                 properties = new Properties();
                 properties.load(is);
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
        
         public static <T> T get(String name) {
             try {
                 // 类名
                 String clsName = properties.getProperty(name);
                 Class cls = Class.forName(clsName);
                 // 实例化对象
                 return (T) cls.newInstance();
             } catch (Exception e) {
                 e.printStackTrace();;
             }
             return null;
         }
         public static PersonService getService() {
             return get("personService");
         }
        
         public static PersonDao getDao() {
             return get("personDao");
         }
     }
    
  3. 这样,如果替换service、dao的实现类,只需要修改配置文件中的实现类字符串即可

4.封装一个通用的工厂

  1. 封装通用工厂GeneralFactory

     public class GeneralFactory {
         private static Properties properties;
         static {
             try (InputStream is = GeneralFactory.class.getClassLoader().getResourceAsStream("factory.properties")) {
                 properties = new Properties();
                 properties.load(is);
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
        
         public static <T> T get(String name) {
             try {
                 // 类名
                 String clsName = properties.getProperty(name);
                 Class cls = Class.forName(clsName);
                 // 实例化对象
                 return (T) cls.newInstance();
             } catch (Exception e) {
                 e.printStackTrace();;
             }
             return null;
         }
     }
    
  2. servlet、dao中改造

     //PersonServlet
     private PersonService service = GeneralFactory.get("personService");
     //PersonServiceImpl
     private PersonDao dao = GeneralFactory.get("personDao");
    

IoC是什么

  1. Spring已经内置了这样的全局工厂(ApplicationContext),不需要自己实现—IoC
  2. 即对javaEE语法的封装,封装一个全局工厂类(ApplicationContext),可以通过配置文件中配置的类字符串创建一个实例

基本使用-IoC容器

  1. 添加Maven依赖项

     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context</artifactId>
         <version>5.2.9.RELEASE</version>
     </dependency>
    
  2. 添加一个核心配置文件 applicationContext.xml
    1. 右击resources->new->XML Configuration File ->Spring Config->applicationContext.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就是代表Spring将要创建的对象,类似之前的factory.properties-->
           <bean id="personDao" class="com.zh.dao.impl.PersonDaoImpl"/>
           <bean id="personService" class="com.zh.service.impl.PersonServiceImpl">
               <!--
               property就是这个对象对应的属性,因此这个对象必须要有对应的这个属性,否则会报错
               1. 会主动调用PersonServiceImpl对象的dao属性的set方法-setDao方法
               2. 调用set方法传的的参数值为:ref引用的类型的实例对象,也要创建一个参数对象
               3. 因此要在PersonServiceImpl对象中实现dao属性的set方法
               -->
               <property name="dao" ref="personDao"/>
           </bean>
              
           <bean id="personServlet" class="com.zh.servlet.PersonServlet">
               <property name="service" ref="personService"/>
           </bean>
       </beans>
      
      1. bean标签对应对象、property对应对象的属性,ref要传入的参数类型
    2. 那么如何获取这个xml文件,并出创建bean标签对应的对象呢?—全局类工厂

       // 读取配置文件
       ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
       //创建servlet对象
       PersonServlet servlet = ctx.getBean("personServlet", PersonServlet.class);
       servlet.remove();
      
  3. 根据核心配置文件在PersonServlet添加私有的service属性、PersonServiceImpl中添加私有的dao属性,并分别实现其对应的set方法
    1. PersonServlet

       public class PersonServlet {
           private PersonService service;
           public void setService(PersonService service) {
               this.service = service;
           }
           //模拟网络请求调用:删除一条数据
           public void remove() {
               service.remove(1);
           }
              
           public static void main(String[] args) {
               // 读取配置文件
               ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
               //通过id获取bean对象,并强制转换传成PersonServlet类
               PersonServlet servlet = ctx.getBean("personServlet", PersonServlet.class);
               servlet.remove();
           }
       }
      
    2. PersonServiceImpl

       public class PersonServiceImpl implements PersonService {
           private PersonDao dao;
           public void setDao(PersonDao dao) {
               this.dao = dao;
           }
           @Override
           public boolean remove(Integer id) {
               return dao.remove(id);
           }
       }
      

IoC容器总结

  1. IoC简称:Inversion of Control,控制反转,对象的创建控制权转交给了Spring
  2. 对javaEE语法的封装,封装一个全局工厂类(ApplicationContext),可以通过配置文件中配置的类字符串(ben标签)创建一个实例,即核心一是配置文件applicationContext.xml、二是全局工厂类
  3. IoC容器指的是xml里面放了很多的bean,被创建完的对象都放在了一个容器中
    1. 注意:从Spring开始模型对象的文件就不能叫bean了,以后所说的bean都是spring那个xml文件中的bean标签,模型对象用domain文件存储
  4. IoC的一个很重要的作用:解耦,它实现了将dao、service、servlet三层进行解耦,只需要通过修改配置文件即可修改三层的依赖关系。

scope

  1. 可以通过scope属性控制IOC中创建的bean是否单例
    1. singleton:单例(默认)
      1. 通过同一个id值,在同一个IoC容器中(同一个ctx对象)获取的永远是同一个实例
      2. 在IoC容器创建的时候,就会创建bean,可以设置lazy-init为true修改创建时机
      3. 注意:这个单例仅仅是在这个容器中
    2. prototype: :非单例,每次getBean时创建一次bean
  2. 参考资料:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-scopes
  3. 代码举例:
    1. Dog类

       public class Dog {
           //监听dog什么时间被创建
           public Dog() {
               System.out.println("Dog----------");
           }
       }
      
    2. applicationContext.xml

       <!--<bean id="dog" class="com.zh.domain.Dog"/>-->
       <!--与上面等价,每次通过getBean获取是同一个对象-->
       <bean id="dog" class="com.zh.domain.Dog" scope="singleton"/>
              
       <!--不同id值,与上面获取的不同-->
       <bean id="dog2" class="com.zh.domain.Dog" scope="singleton"/>
          
       <!--每次通过getBean获取不是同一个对象-->
       <bean id="dog3" class="com.zh.domain.Dog" scope="prototype"/>
          
       <!--dog、dog3都是创建容器时就已经创建了,dog2是调用getBean时创建-->
       <bean id="dog4" class="com.zh.domain.Dog" lazy-init="true"/>
      
    3. 测试代码:

       @Test
       public void test() {
           //一个ctx代表创建一个IoC一个容器,创建这个容器的时候已经将xml中所有的bean对象创建
           ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
           //在调用getBean前,dog对象已经被创建了
           System.out.println(ctx.getBean("dog", Dog.class)); 
           System.out.println(ctx.getBean("dog", Dog.class)); //与上面一样
           System.out.println(ctx.getBean("dog2", Dog.class)); //与上面不一样
           System.out.println(ctx.getBean("dog3", Dog.class));
           System.out.println(ctx.getBean("dog3", Dog.class)); //与上面不一样,属性为prototype
           System.out.println(ctx.getBean("dog4", Dog.class)); //用到时才创建
                  
            //不同容器,对象不一样
           ApplicationContext ctx2 = new ClassPathXmlApplicationContext("applicationContext.xml");
           //在调用getBean前,dog对象已经被创建了
           System.out.println(ctx2.getBean("dog", Dog.class));
       }
      

Spring集成日志框架logback

  1. Spring可以轻松整合日志框架:logback

     <dependency>
         <groupId>ch.qos.logback</groupId>
         <artifactId>logback-classic</artifactId>
         <version>1.2.3</version>
     </dependency>
    
  2. 通过导入logback,能通过日志看到PersonServlet servlet = ctx.getBean("personServlet", PersonServlet.class);具体做了什么

     21:41:12.407 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4e9ba398
     21:41:13.292 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 3 bean definitions from class path resource [applicationContext.xml]
     21:41:13.439 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'personDao'
     21:41:13.523 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'personService'
     21:41:13.799 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'personServlet'
    

依赖注入DI(Dependency Injection)

概念

  1. 引入:
    1. 在上面讲解IoC的时候就讲解过依赖注入,比如: PersonServiceImpl这个类依赖于dao这个属性,通过applicationContext.xml这个<property name="dao" ref="personDao"/>属性标签,将ref这个类型的对象通过setter方法注入到了PersonServiceImpl对象中
    2. 注意: 这里面的ref引用的对象正好能在applicationContext.xml文件中的id找到
  2. 所谓的注入就是: 给applicationContext.xml配置的这些bean对象设置属性,等到真正使用这些bean时会根据这些设置进行实例化
    1. 如果说IOC是封装一个全局类来读取配置文件创建实例(bean)的话,那么DI就是封装一套API在IOC创建实例(bean)时依据配置文件中配置的实例(bean)属性来创建所有的属性值。
  3. 常见的注入内容(属性类型)可以分为3大类
    1. bean(自定义类型)
    2. 基本类型、String、BigDecimal
    3. 集合类型(数组、Map、List、Set、Properties)
  4. 常见的注入方式有2种,即要使用这套API的话,对应属性的内容必须实现2以下两种任意一种。
    1. 基于setter(属性)
    2. 基于Constructor(构造方法)

基于setter的注入

//新建一个项目,添加两个模型Dog、Person
public class Person {
    private int age;
    private String name;
    private BigDecimal money;
    private Dog dog;
    private Set<String> nickNames;
    private Properties friends;
}
  1. 基本类型、String、BigDecimal的注入:
    1. 实现Person类所有属性的setter方法
    2. applicationContext.xml中如下

       <bean id="person" class="com.zh.domain.Person">
           <!--基本数据类型注入-->
           <property name="age" value="18"/>
           <property name="money" value="100.5"/>
           <property name="name" value="Jack"/>
       </bean>
      
  2. bean自定义类型
    1. applicationContext.xml中如下

       <bean id="dog" class="com.zh.domain.Dog"/>
       <bean id="person" class="com.zh.domain.Person">
           <!--对象类型注入-->
           <!--方式1-->
           <!--<property name="dog" ref="dog"/>-->
           <!--方式2-->
           <property name="dog">
               <ref bean="dog"/>
           </property>
           <!--方式3:这种方式,这只dog跟外面的bean中的dog不一样-->
           <!--<property name="dog">-->
               <!--<bean class="com.zh.domain.Dog"/>-->
           <!--</property>-->
       </bean>
      
  3. 集合类型

     <!--集合方式注入-->
     <property name="nos">
         <array>
             <value>11</value>
             <value>11</value>
         </array>
     </property>
     <property name="nos">
         <list>
             <value>11</value>
             <value>11</value>
         </list>
     </property>
     <!-- LinkeHashSet -->
     <property name="pones">
         <set>
             <value>Jack</value>
             <value>Rose</value>
             <value>James</value>
         </set>
     </property>
     <!-- LinkeHashSet -->
     <property name="friends">
         <map>
             <entry key ="Jack" value="广州“/>
             <entry key ="Rose" value=”背景“/>
             <entry key ="James" value="上海”/>
         </map>
     </property>
        
     <property name="friends">
         <props>
             <prop key="Jack">杰克</prop>
             <prop key="Rose">螺丝</prop>
         </props>
     </property>
    

另外一种方法:

  1. 在applicationContext.xml文件的beans根标签添加属性:(需要先在根标签加一个命名空间属性)

     xmlns:p="http://www.springframework.org/schema/p"
    
  2. 使用如下:

     <!--
     //只适用于setter方法的注入:
     1. 跟标签添加命名空间属性: xmlns:p="http://www.springframework.org/schema/p"
     2. 通过p来注入属性
     -->
        
     <bean id="dog" class="com.zh.domain.Dog"/>
     <!--这个dog-ref属性,是根据所有bean对象的id属性自动生成的-->
     <bean id="person" class="com.zh.domain.Person"
           p:name="Jack" p:age="18" p:dog-ref="dog"/>
    

基于Constructor的注入

  1. 前提条件: 必须实现实现Person属性对应的构造方法

     public Person() {
         System.out.println("Person()");
     }
    
     public Person(int age) {
         this.age = age;
         System.out.println("Person(" + age + ")");
     }
    
     @ConstructorProperties({"age", "name"})
     public Person(int age, String name) {
         this.age = age;
         this.name = name;
         System.out.println("Person(" + age + ", " + name + ")");
     }
    
  2. 基本类型、String、BigDecimal的注入:

     <bean id="person" class="com.zh.domain.Person">
         <!--方法1:--> 
    <!--        <constructor-arg type="int" value="22"/>-->
    <!--        <constructor-arg type="java.lang.String" value="Jack"/>--> 
         <!--方法2:-->
    <!--        <constructor-arg index="0" value="22"/>-->
    <!--        <constructor-arg index="1" value="Jack"/>-->
         <!--方法3:
         注意该方法使用:需要在构造方法前加上注解@ConstructorProperties({"age", "name"})
         -->
         <constructor-arg value="Jack666" name="name"/>
         <constructor-arg value="28" name="age"/>
     </bean>
    
  3. bean自定义类型

     <bean id="dog" class="com.zh.domain.Dog"/>
     <!--    <bean id="person" class="com.zh.domain.Person">-->
     <!--        <constructor-arg ref="dog"/>-->
     <!--    <<!--    </bean>-->
     <bean id="person" class="com.zh.domain.Person">
         <constructor-arg>
             <ref bean="dog"/>
         </constructor-arg>
     </bean>
     <!-- <bean id="person" class="com.zh.domain.Person">-->
     <!--        <constructor-arg>-->
     <!--            <bean id="dog" class="com.zh.domain.Dog"/>-->
     <!--        </constructor-arg>-->
     <!--    </bean>-->
    
  4. 集合类型

     <bean id="person" class="com.zh.domain.Person">
         <constructor-arg>
             <list>
                 <value>Jack</value>
                 <value>Rose</value>
             </list>
         </constructor-arg>
     </bean>
    

复杂对象的注入

  1. 指的是创建过程比较复杂的对象:比如创建一个对象不是通过new Class创建的,而是通过自定义的类方法、实例发方法创建的,那么在xml文件中改如何写呢?

实例工厂、静态工厂

  1. 创建一个ConnectionFactory类

     //com.zh.obj.ConnectionFactory
     public class ConnectionFactory {
         private String driverClass;
         private String url;
         private String username;
         private String password;
        
         public void setDriverClass(String driverClass) {
             this.driverClass = driverClass;
         }
        
         public void setUrl(String url) {
             this.url = url;
         }
        
         public void setUsername(String username) {
             this.username = username;
         }
        
         public void setPassword(String password) {
             this.password = password;
         }
         //类方法创建
         public static Connection getConn1() throws Exception {
             Class.forName("com.mysql.jdbc.Driver");
             return DriverManager.getConnection("jdbc:mysql://localhost:3306/test-mybatis", "root", "root");
         }
         //实例方法创建
         public Connection getConn2() throws Exception {
             Class.forName(driverClass);
             return DriverManager.getConnection(url, username, password);
         }
     }
    
  2. applicationContext.xml文件

     <!-- 方式1;静态工厂方法(调用ConnectionFactory.getConn1()) -->
     <bean id="conn1" class="com.zh.obj.ConnectionFactory" factory-method="getConn1"/>
    
     <!-- 方式2: 实例工厂方法(调用factory.getConn2()) -->
     <!-- 1. 先创建实例对象-->
     <bean id="factory" class="com.zh.obj.ConnectionFactory">
         <property name="driverClass" value="com.mysql.jdbc.Driver"/>
         <property name="url" value="jdbc:mysql://localhost:3306/test-mybatis"/>
         <property name="username" value="root"/>
         <property name="password" value="root"/>
     </bean>
     <!-- 2.通过实例对象创建-->
     <bean id="conn2" factory-bean="factory" factory-method="getConn2"/>
    

FactoryBean

  1. 创建一个ConnectionFactoryBean类,并实现FactoryBean接口,而且实现接口对应的方法

     //实现FactoryBean接口
     public class ConnectionFactoryBean implements FactoryBean<Connection> {
         private String driverClass;
         private String url;
         private String username;
         private String password;
    
         //上面属性对应的set方法,略  
              
         //必须实现
         @Override
         public Connection getObject() throws Exception {
             Class.forName(driverClass);
             return DriverManager.getConnection(url, username, password);
         }
        
         //必须实现
         @Override
         public Class<?> getObjectType() {
             return Connection.class;
         }
     }
    
    1. 注意:定义这个类的目的并不是为了获取ConnectionFactoryBean对象,而是为了获取DriverManager.getConnection()这个对象(getObject可以拿到),用来连接数据库。
  2. applicationContext.xml文件

     <!--方式3: FactoryBean
      1. 首先自动创建ConnectionFactoryBean对象
      2. 自动给对象注入属性
      3. 调用实例对象的getObject方法
      -->
     <bean id="conn" class="com.zh.obj.ConnectionFactoryBean">
         <property name="driverClass" value="com.mysql.jdbc.Driver"/>
         <property name="url" value="jdbc:mysql://localhost:3306/test-mybatis"/>
         <property name="username" value="root"/>
         <property name="password" value="root"/>
     </bean>
    
  3. Spring内部会做如下事情:
    1. 首先自动创建ConnectionFactoryBean实例对象
    2. 根据property给对象注入属性
    3. 调用实例对象的getObject方法
  4. 测试代码

     @Test
     public void test() {
         ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
         //getBean("conn")表面上获取的是ConnectionFactoryBean,而实际获取的是getObject这个返回值。
         System.out.println(ctx.getBean("conn"));
         //&开头代表创建的是FactoryBean类型的对象,这个获取的才是ConnectionFactoryBean实例。
         System.out.println(ctx.getBean("&conn"));
     }
    
  5. 总结:
    1. 使用工厂方法创建对象,注入的时候需要指定factory-method的工厂方法
    2. 使用FactoryBean跟的话不需要指定factory-method,直接在配置文件中配置对应的FactoryBean,spring内部会自动调用FactoryBean的getObject方法,获取到真正的实例对象
    3. 这是FactoryBean的一个典型使用,即xml中注册的是一个FactoryBean类,但是该容器中创建的通常是factory这个对象

引入其他配置文件

  1. 上面看到如果想要数据库的引入可配置化,那就需要使用配置文件,在resources文件夹下创建db.properties

     jdbc.driverClass=com.mysql.jdbc.Driver
     jdbc.url=jdbc:mysql://localhost:3306/test-mybatis
     jdbc.username=root
     jdbc.password=root
    
  2. applicationContext.xml的根标签beans添加:

     //引入命名空间
     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">
    
  3. 改造:

     <!-- 引用db.properties文件的内容 -->
     <context:property-placeholder location="db.properties"/>
     <bean id="conn" class="com.zh.obj.ConnectionFactoryBean">
         <property name="driverClass" value="${jdbc.driverClass}"/>
         <property name="url" value="${jdbc.url}"/>
         <!--${}里面不能使用username,是保留字-->
         <property name="username" value="${jdbc.username}"/>
         <property name="password" value="${jdbc.password}"/>
     </bean>
    

SpEL表达式

  1. 使用方式#{}
  2. 官方文档:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#expressions
  3. Dog、Person类

     public class Dog {
         public String getTestName() {return "WangCai";}
         public int getTestAge() {return 99;}
     }
        
     public class Person {
         private String name;
         private int age;
         private Dog dog;
        
         public String getName() {return name;}
        
         public void setName(String name) { this.name = name;}
        
         public int getAge() { return age;}
        
         public void setAge(int age) { this.age = age;}
        
         public Dog getDog() {return dog;}
        
         public void setDog(Dog dog) { this.dog = dog;}
        
         @Override
         public String toString() {
             return "Person{" +
                     "name='" + name + '\'' +
                     ", age=" + age +
                     ", dog=" + dog +
                     '}';
         }
     }
    
  4. applicationContext.xml使用

     <bean id="dog" class="com.zh.domain.Dog"/>
    
     <bean id="person" class="com.zh.domain.Person">
         <property name="dog" value="#{dog}"/>
         <property name="age" value="#{dog.testAge}"/>
         <!--<property name="name" value="#{dog.testName.bytes.length}"/>-->
         <property name="name" value="#{dog.getTestName()}"/>
     </bean>
    
  5. ConnTest测试代码

     @Test
     public void spEl() {
         ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
         System.out.println(ctx.getBean("person"));
     }
    
Table of Contents