Spring(一)基于XML的配置

Spring(一)基于XML的配置

1.spring 是什么

Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control:反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层 SpringMVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架

2.spring 的优势

方便解耦,简化开发

通过 Spring 提供的 IoC 容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。

AOP 编程的支持

通过 Spring 的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以 通过 AOP 轻松应付。

声明式事务的支持

可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务的管理,提高开发效率和质量。

方便程序的测试

可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情。

方便集成各种优秀框架

Spring 可以降低各种框架的使用难度,提供了对各种优秀框架(Struts、Hibernate、Hessian、 Quartz等)的直接支持。

降低 JavaEE API 的使用难度

Spring 对 JavaEE API(如 JDBC、 JavaMail、远程调用等)进行了薄薄的封装层,使这些 API 的使用难度大为降低。

Java 源码是经典学习范例

Spring 的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对 Java 设计模式灵活运用以及对 Java 技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。

3.使用Spring的IOC解耦和

3.1基于XML的配置

导包

创建bean.xml

导入约束

在配置文件中配置 service 和 dao

<!--bean.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">
<!--配置Service-->
<bean id="accountService" class="fun.chenqi.service.impl.AccountServiceImpl"/>
<!--配置Dao-->
<bean id="accountDao" class="fun.chenqi.dao.impl.AccountDaoImpl"/>

//测试类
@Test
   public void test() {
       // 使用ApplicationContext接口,获取Spring容器
       ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
       // 根据bean的ID获取对象
       IAccountService aService = (IAccountService) ac.getBean("accountService");
       aService.saveAccount();
   }

3.2.Spring 基于 XML 的 IOC 细节

BeanFactory 和 ApplicationContext 的区别

BeanFactory 才是 Spring 容器中的顶层接口。ApplicationContext 是它的子接口。BeanFactory 和 ApplicationContext 的区别:创建对象的时间点不一样。ApplicationContext:只要一读取配置文件,默认情况下就会创建对象。BeanFactory:什么使用什么时候创建对象。

ApplicationContext 接口的实现类

ClassPathXmlApplicationContext:它是从类的根路径下加载配置文件。推荐使用这种FileSystemXmlApplicationContext:它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。AnnotationConfigApplicationContext:当我们使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。

IOC 中 bean 标签和管理对象细节
bean 标签
 <!--配置bean-->
   <!--
   bean作用:
   用于配置对象让 spring 来创建的。
   默认情况下它调用的是类中的无参构造函数。如果没有无参构造函数则不能创建成功。
   属性:
   id: 给对象在容器中提供一个唯一标识。用于获取对象。
   class: 指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数。
   scope: 指定对象的作用范围。
           * singleton :默认值,单例的.
           一个应用只有一个对象的实例。它的作用范围就是整个引用。
           生命周期:
           对象出生:当应用加载,创建容器时,对象就被创建了。
           对象活着:只要容器在,对象一直活着。
           对象死亡:当应用卸载,销毁容器时,对象就被销毁了。
           * prototype :多例的.
           每次访问对象时,都会重新创建对象实例。
           生命周期:
           对象出生:当使用对象时,创建新的对象实例。
           对象活着:只要对象在使用中,就一直活着。
           对象死亡:当对象长时间不用时,被 java 的垃圾回收器回收了。

           * request :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中.
           * session :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中.
           * global session :WEB 项目中,应用在 Portlet 环境.如果没有 Portlet 环境那么
   globalSession 相当于 session.
   init-method: 指定类中的初始化方法名称。
   destroy-method: 指定类中销毁方法名称。
   -->
   <!--默认使用无参构造实例化Bean-->
   <!---->
   <bean id="accountService" class="fun.chenqi.service.impl.AccountServiceImpl"/>
实例化 Bean 的三种方式
<!--第一种默认使用无参构造实例化Bean-->
   <bean id="accountService" class="fun.chenqi.service.impl.AccountServiceImpl"/>

第二种:

public class StaticFactory {
   public static IAccountService createAccountService() {
       return new AccountServiceImpl();
    }
}
<!--此种方式是:
    使用 StaticFactory 类中的静态方法 createAccountService 创建对象,并存入 spring 容器
    id 属性:指定 bean 的 id,用于从容器中获取
    class 属性:指定静态工厂的全限定类名
    factory-method 属性:指定生产对象的静态方法
    -->
   <bean id="accountServiceStatic"
         class="fun.chenqi.factory.StaticFactory"
         factory-method="createAccountService"
   />
IAccountService sf = (IAccountService) ac.getBean("accountServiceStatic");
       sf.saveAccount();
       System.out.println(sf);

第三种:

public class InstanceFactory {
   public IAccountService createAccountService() {
       return new AccountServiceImpl();
    }
}
    <!--此种方式是:
       先把工厂的创建交给 spring 来管理。
       然后在使用工厂的 bean 来调用里面的方法
       factory-bean 属性:用于指定实例工厂 bean 的 id。
       factory-method 属性:用于指定实例工厂中创建对象的方法。
   -->
   <bean id="accountService1" factory-method="createAccountService" factory-bean="instanceFactory"/>
   <bean id="instanceFactory" class="fun.chenqi.factory.InstanceFactory"/>

IAccountService inf = (IAccountService) ac.getBean("accountService1");
       inf.saveAccount();
       System.out.println(inf);

3.3spring的依赖注入

依赖注入: Dependency Injection。 它是 spring 框架核心 ioc 的具体实现。我们的程序在编写时, 通过控制反转, 把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。ioc 解耦只是降低他们的依赖关系,但不会消除。 例如:我们的业务层仍会调用持久层的方法。那这种业务层和持久层的依赖关系, 在使用 spring 之后, 就让 spring 来维护了。简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。

构造函数注入
// 构造函数注入
// 顾名思义,就是使用类中的构造函数,给成员变量赋值。注意,赋值的操作不是我们自己做的,而是通过配置
// 的方式,让 spring 框架来为我们注入
public class ZhuRuImpl implements IZhuRu {
   private String name;
   private int age;
   private Date bir;
   public ZhuRuImpl(String name, int age, Date bir) {
       this.name = name;
       this.age = age;
       this.bir = bir;
   }
}
<!--构造方法注入
       使用构造函数的方式,给 service 中的属性传值
       要求:
       类中需要提供一个对应参数列表的构造函数。
       涉及的标签:
       constructor-arg
       属性:
       index:指定参数在构造函数参数列表的索引位置
       type:指定参数在构造函数中的数据类型
       name:指定参数在构造函数中的名称 用这个找给谁赋值
       =======上面三个都是找给谁赋值,下面两个指的是赋什么值的==============
       value:它能赋的值是基本数据类型和 String 类型
       ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean-->
   <bean id="zhuru01" class="fun.chenqi.service.impl.ZhuRuImpl">
       <constructor-arg index="0" value="陈琦"/>
       <constructor-arg index="1" value="23"/>
       <constructor-arg index="2" ref="date"/>
   </bean>
   <bean id="date" class="java.util.Date"/>
set方法注入
// set 方法注入
public class ZhuRuImpl02 implements IZhuRu {

   private String name;
   private int age;
   private Date bir;

   public void setName(String name) {
       this.name = name;
   }

   public void setAge(int age) {
       this.age = age;
   }

   public void setBir(Date bir) {
       this.bir = bir;
   }
<!-- 通过配置文件给 bean 中的属性传值:使用 set 方法的方式
          涉及的标签: property
          属性:
          name:找的是类中 set 方法后面的部分
          ref:给属性赋值是其他 bean 类型的
          value:给属性赋值是基本数据类型和 string 类型
-->
   <bean id="zhuru02" class="fun.chenqi.service.impl.ZhuRuImpl02">
       <property name="name" value="ss"/>
       <property name="age" value="11"/>
       <property name="bir" ref="date"/>
   </bean>
<bean id="date" class="java.util.Date"/>
注入集合属性
// 注入集合属性
public class ZhuRuImpl03 implements IZhuRu {
   private String[] myStrs;
   private List<String> myList;
   private Set<String> mySet;
   private Map<String, String> myMap;
   private Properties myProps;

   public void setMyStrs(String[] myStrs) {
       this.myStrs = myStrs;
   }

   public void setMyList(List<String> myList) {
       this.myList = myList;
   }

   public void setMySet(Set<String> mySet) {
       this.mySet = mySet;
   }

   public void setMyMap(Map<String, String> myMap) {
       this.myMap = myMap;
   }

   public void setMyProps(Properties myProps) {
       this.myProps = myProps;
   }
}
<!-- 注入集合数据
           List 结构的:
           array,list,set
           Map 结构的
           map,entry,props,prop
-->
   <bean id="zhuru03" class="fun.chenqi.service.impl.ZhuRuImpl03">
       <!-- 在注入集合数据时,只要结构相同,标签可以互换 -->
       <property name="myList">
           <list>
               <value>111</value>
               <value>222</value>
               <value>333</value>
           </list>
       </property>

       <property name="myMap">
           <map>
               <entry key="1" value="11"/>
               <entry key="2" value="22"/>
               <entry key="3" value="33"/>
           </map>
       </property>

       <property name="myProps">
           <props>
               <prop key="1">11</prop>
               <prop key="2">22</prop>
               <prop key="3">33</prop>
           </props>
       </property>
       <property name="mySet">
           <set>
               <value>111</value>
               <value>333</value>
               <value>222</value>
           </set>
       </property>
       <property name="myStrs">
           <array>
               <value>111</value>
               <value>222</value>
               <value>333</value>
           </array>
       </property>
   </bean>

基于XML的CRUD

<?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">

   <!--配置service set注入-->
   <!-- AccountServiceImpl impl = new AccountServiceImpl() -->
   <bean id="accountService" class="fun.chenqi.service.impl.AccountServiceImpl">
       <property name="dao" ref="accountDao"/>
   </bean>

   <!--配置dao-->
   <!--  AccountDaoImpl impl = new AccountDaoImpl()  -->
   <bean id="accountDao" class="fun.chenqi.dao.impl.AccountDaoImpl">
       <property name="qr" ref="runner"/>
   </bean>
   <!-- 配置 QueryRunner -->
   <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
       <constructor-arg name="ds" ref="dataSource"/>
   </bean>
   <!-- 配置c3p0数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
      <property name="driverClass" value="com.mysql.jdbc.Driver"/>
      <property name="jdbcUrl" value="jdbc:mysql:///chenqi"/>
      <property name="user" value="root"/>
      <property name="password" value="111"/>
  </bean>
   <!-- 配置dbcp数据源
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
       <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
       <property name="url" value="jdbc:mysql://localhost:3306/chenqi"/>
       <property name="username" value="root"/>
       <property name="password" value="111"/>
   </bean> -->
</beans>
public class AccountTest {

   @Test
   public void ins() throws SQLException {
       ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
       IAccountService service = (IAccountService) ac.getBean("accountService");
       Account account = new Account();
       account.setName("1234");
       account.setMoney(1000.0);
       service.insert(account);
   }

   @Test
   public void del() throws SQLException {
       ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
       IAccountService service = (IAccountService) ac.getBean("accountService");
       int i = 5;
       service.delect(i);
   }

   @Test
   public void upd() throws SQLException {
       ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
       IAccountService service = (IAccountService) ac.getBean("accountService");
       Account account = new Account();
       account.setId(1);
       account.setName("1222");
       account.setMoney(9000.0);
       service.update(account);
   }

   @Test
   public void sel() throws SQLException {
       ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
       IAccountService service = (IAccountService) ac.getBean("accountService");
       Object runner = ac.getBean("runner");
       Object dao = ac.getBean("accountDao");
       service.select();
   }
}
public class AccountServiceImpl implements IAccountService {
   // IAccountDao dao = new AccountDaoImpl();// 有依赖
   IAccountDao dao; // 无依赖
   // set 注入
   public void setDao(IAccountDao dao) {
       this.dao = dao;
   }
   @Override
   public void insert(Account account) throws SQLException {
       dao.insert(account);
   }
   @Override
   public void delect(int i) throws SQLException {
       dao.delete(i);
   }
   @Override
   public void update(Account account) throws SQLException {
       dao.update(account);
   }
   @Override
   public List<Account> select() throws SQLException {
       return dao.select();
   }
}
public class AccountDaoImpl implements IAccountDao {
   private QueryRunner qr;
   public void setQr(QueryRunner qr) {
       this.qr = qr;
   }
   @Override
   public List<Account> select() throws SQLException {
       List<Account> list = null;
       try {
           String sql = "select * from account";
           list = qr.query(sql, new BeanListHandler<Account>(Account.class));
           for (Account account : list) {
               System.out.println(account);
           }
           return list;
       } catch (SQLException e) {
           e.printStackTrace();
       }
       return null;
   }
   @Override
   public void update(Account account) throws SQLException {
       String sql = "update account set name = ? , money = ? where id = ?";
       int i = qr.update(sql, account.getName(), account.getMoney(), account.getId());
       if (i > 0) {
           System.out.println("OK!");
       }
   }
   @Override
   public void delete(int i) throws SQLException {
       String sql = "delete from account where id = ?";
       int a = qr.update(sql, i);
       if (a > 0) {
           System.out.println("OK!");
       }
   }
   @Override
   public void insert(Account account) throws SQLException {
       String sql = "insert into account values(null,?,?)";
       int i = qr.update(sql, account.getName(), account.getMoney());
       if (i > 0) {
           System.out.println("OK!");
       }
   }
}

发表评论