Spring笔记,作者:赵

目录

1.Spring的概念

2.Spring项目环境搭建

3.Spring 中的 Bean 配置

4.依赖注入的方法

5.内部 Bean与级联属性

6.集合属性,List,Map,Set,Properties,数组

7.使用 p 命名空间

8.utility scheme 定义集合

9.Bean 自动装配

10.继承 Bean

11.使用外部属性文件

12.基于注解的方式配置Bean

13.spring表达式语言:SpEL

14.IOC 容器中 Bean 的生命周期方法

15.创建 Bean 的工厂方法

16.泛型依赖注入

17.Aop动态代理

18.Aop切面,基于 注解的方式声明切面

19.基于 XML配置声明切面

20.JdbcTemplate, JdbcDaoSupport 示例代码,具名参数

21.Spring 中的事务管理


1.Spring的概念

创建时间:2018/7/17 20:49
更新时间:2018/7/18 11:26
作者:1876333166@qq.com

 

  • Spring 是一个开源框架.

  • Spring 为简化企业级应用开发而生. 使用 Spring 可以使简单的 JavaBean 实现以前只有 EJB 才能实现的功能.

  • Spring 是一个 IOC(DI)  AOP 容器框架.

 

  • 具体描述 Spring:

    • 轻量级Spring 是非侵入性 - 基于 Spring 开发的应用中的对象可以不依赖于 Spring  API

    • 依赖注入(DI --- dependency injectionIOC)

    • 面向切面编程(AOP --- aspect oriented programming)

    • 容器: Spring 是一个容器, 因为它包含并且管理应用对象的生命周期

    • 框架: Spring 实现了使用简单的组件配置组合成一个复杂的应用.  Spring 中可以使用 XML  Java 注解组合这些对象

    • 一站:在 IOC  AOP 的基础上可以整合各种企业应用的开源框架和优秀的第三方类库 (实际上 Spring 自身也提供了展现层的 SpringMVC 和 持久层的 Spring JDBC

    第一步:下载 springsource-tool-suite-3.4.0.RELEASE-e4.3.1-updatesite.zip 插件

 第二步 :安装插件

    打开Eclipse ------> Help -----> Install New Software ----->add ---->Archive ----->找到下载的插件打开勾选IDE结尾的选项 ----> Click Next  and then Finish

----->Restart eclipse when that is asked

    第三步:检查插件是否安装成功

            打开Eclipse ---->File ----> New -----> Other  搜索Spring如果有说明成功

 


2.Spring项目环境搭建

创建时间:2018/7/18 8:53
更新时间:2018/8/3 10:36
作者:1876333166@qq.com

 

 

第一步:创建一个Web项目,把spring的jar导入到lib目录下面

   下载地址: https://repo.spring.io/webapp/#/artifacts/browse/tree/General/libs-release-local/org/springframework/spring/4.3.2.RELEASE

需要导入的jar:

  1.  commons-logging-1.1.3.jar

  2.  spring-beans-4.3.0.RELEASE.jar

  3.  spring-context-4.3.0.RELEASE.jar

  4.  spring-core-4.3.0.RELEASE.jar

  5.  spring-expression-4.3.0.RELEASE.jar

 

第二步:创建一个实体类如下:给上set,get,构造方法,toString方法(方便查看结果)

            

package com.yirong.bean;

public class Person {

     private int price;

     private String book;

}

第三步:创建spring的配置文件 在需要放配置文件的目录下鼠标右键----> New ----> Other ---->  搜索Spring ------> 找到Spring Bean Configuration File ----> Next ---- > 输入配置文件的名字后缀是.xml -----> Next 勾选beans -----> Next ----- > Finish----->文件创建成功

 

第四步:为第二步实体类配置bean(一个bean就是一个容器) 结构如下

 

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">

     <!-- 通过全类名方式配置Bean id:自己设定,最好为实体类的小写  class:实体类的全路径-->

     <bean id="name" class="com.yirong.bean.Person">

          <!-- name:填入的参数是实体类的属性 value:需要给属性赋的值 -->

          <property name="price" value="200"></property>

          <property name="book" value="编程设计思想"></property>

     </bean>

     

</beans>

 

第五步:写测试类,测试实体类属性是否赋值成功

    

package com.yirong.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.yirong.bean.Person;

public class Test {

     public static void main(String[] args) {

          

          //不使用spring,给Person实体类赋值,方法

          Person person = new Person();  //获取实体类对象

          person.setBook("编程思想设计");   //通过set方法给属性赋值

          person.setPrice(1000);        

          System.out.println(person);   //打印实体类结果

          

          //使用spring方法给属性赋值

          //1.创建spring的Ioc容器 spring容器xml文件名字

          ClassPathXmlApplicationContext x = new ClassPathXmlApplicationContext("applicationContext.xml");

          //2.从bean的容器中获取bean的实例

          Person person2 = (Person) x.getBean("person");

          //3.打印实体类结果

          System.out.println(person2);

     }

}

 


3.Spring 中的 Bean 配置

创建时间:2018/7/18 10:01
更新时间:2018/7/18 11:26
作者:1876333166@qq.com

 

  • IOC(Inversion of Control):其思想是反转资源获取的方向. 传统的资源查找方式要求组件向容器发起请求查找资源. 作为回应, 容器适时的返回资源. 而应用了 IOC 之后, 则是容器主动地将资源推送给它所管理的组件, 组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式

  • DI(Dependency Injection) — IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如: setter 方法)接受来自如容器的资源注入. 相对于 IOC 而言,这种表述更直接

  • 配置 bean

    • 配置形式:基于 XML 文件的方式;

    • Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean

    • IOC 容器 BeanFactory & ApplicationContext 概述

    • 依赖注入的方式:属性注入;构造器注入

    • 注入属性值细节<![CDATA[</>]]>

  • 在 xml 文件中通过 bean 节点来配置 bean

     

  • id:Bean 的名称。

    •  IOC 容器中必须是唯一的

    •  id 没有指定,Spring 自动将权限定性类名作为 Bean 名字

    • id 可以指定多个名字,名字之间可用逗号、分号、或空格分隔

  • 在 Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC 容器里获取 Bean 实例并使用.

  • Spring 提供了两种类型的 IOC 容器实现.

    • BeanFactory: IOC 容器的基本实现.

    • ApplicationContext: 提供了更多的高级特性. 是 BeanFactory 的子接口.

    • BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory

    • 无论使用何种方式, 配置文件时相同的.

  • ApplicationContext 的主要实现类:

    • ClassPathXmlApplicationContext:从 类路径下加载配置文件

    • FileSystemXmlApplicationContext: 从文件系统中加载配置文件

  • ConfigurableApplicationContext 扩展于 ApplicationContext,新增加两个主要方法:refresh() 和 close(), 让 ApplicationContext 具有启动、刷新和关闭上下文的能力

  • ApplicationContext 在初始化上下文时就实例化所有单例的 Bean

  • WebApplicationContext 是专门为 WEB 应用而准备的,它允许从相对于 WEB 根目录的路径中完成初始化工作


4.依赖注入的方法

创建时间:2018/7/18 10:25
更新时间:2018/7/18 14:12
作者:1876333166@qq.com

 

第一种:属性注入,如下:

  • 属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象

  • 属性注入使用 <property> 元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 <value> 子节点指定属性值

  • 属性注入是实际应用中最常用的注入方式

    <bean id="person" class="com.yirong.bean.Person">

          <!-- name:填入的参数是实体类的属性 value:需要给属性赋的值 -->

          <property name="price" value="200"></property>

          <property name="book" value="编程设计思想"></property>

     </bean>

第二种:构造器注入,如下:

  • 通过构造方法注入Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化后就可以使用。

  • 构造器注入在 <constructor-arg> 元素里声明属性, <constructor-arg> 中没有 name 属性

    <!-- 使用构造方法注入属性 -->

     <bean id="person" class="com.yirong.bean.Person">

          <!-- 

                使用参数的类型匹配属性可以,区分重载的构造器 

                type:类型匹配

                index:下标匹配

                name:名字

          -->

          <!-- 使用参数的类型匹配属性可以,区分重载的构造器 -->

          <constructor-arg value="200" type="int"></constructor-arg>

          <constructor-arg value="java开发" type="String"></constructor-arg>

     </bean>

  public Person(int price, String book) {

          super();

          this.price = price;

          this.book = book;

     }

字面值:

  • 字面值:可用字符串表示的值,可以通过 <value> 元素标签或 value 属性进行注入。

  • 基本数据类型及其封装类、String 等类型都可以采取字面值注入的方式

  • 若字面值中包含特殊字符,可以使用 <![CDATA[]]> 把字面值包裹起来。

引用其它 Bean ,给set,get方法,构造方法

  • 组成应用程序的 Bean 经常需要相互协作以完成应用程序的功能. 使 Bean 能够相互访问, 就必须在 Bean 配置文件中指定对 Bean 的引用

  •  Bean 的配置文件中, 可以通过 <ref> 元素或 ref  属性 Bean 的属性或构造器参数指定对 Bean 的引用.

  • 也可以在属性或构造器里包含 Bean 的声明, 这样的 Bean 称为内部 Bean

下面的Car是一个实体类类型

第一个实体类

package com.yirong.bean;

public class Person {

     private int price;

     private String book;

     private Car car//引用下一个实体类

}

第二个实体类

package com.yirong.bean;

public class Car {

     private String speed;

     private int price

}

Spring配置文件配置

<!-- 配置Person实体类的bean -->

     <bean id="person" class="com.yirong.bean.Person">

     <!-- 为car属性赋值 因为car属性是bean实体类的类型可以使用ref指向容器中的其他bean-->

          <property name="car" ref="car"></property>

     </bean>

     <!-- 配置Car实体类的bean -->

     <bean id="car" class="com.yirong.bean.Car">

          <property name="speed" value="200"></property>

          <property name="price" value="200"></property>

     </bean>


5.内部 Bean与级联属性

创建时间:2018/7/18 14:12
更新时间:2018/7/18 14:13
作者:1876333166@qq.com

内部 Bean

  •  Bean 实例仅仅给一个特定的属性使用时, 可以将其声明为内部 Bean. 内部 Bean 声明直接包含在 <property>  <constructor-arg> 元素里, 不需要设置任何 id  name 属性

  • 内部 Bean 不能使用在任何其他地方

     <!-- 配置Person实体类的bean -->

     <bean id="person" class="com.yirong.bean.Person">

          <!-- 使用内部bean给属性car赋值 -->

          <property name="car">

              <!-- 配置Car实体类的bean -->

              <bean id="car" class="com.yirong.bean.Car">

                   <property name="speed" value="200"></property>

                   <property name="price" value="200"></property>

              </bean>

          </property>

     </bean>

级联属性:Spring 支持级联属性的配置

 

<!-- 配置Person的bean -->

     <bean id="person" class="com.yirong.bean.Person">

          <constructor-arg value="100" index="0"></constructor-arg>

          <constructor-arg value="java开发" index="1"></constructor-arg>

          <constructor-arg ref="car"></constructor-arg>

          <!-- 给Car属性中speed的属性赋值 -->

          <property name="car.speed" value="100"></property>

     </bean>

     <bean id="car" class="com.yirong.bean.Car"></bean>


6.集合属性,List,Map,Set,Properties,数组

创建时间:2018/7/18 14:13
更新时间:2018/7/19 10:42
作者:1876333166@qq.com

 

集合属性,List

第一步创建实体类:为实体类给上set,get,构造toString,方法

package com.yirong.bean;

import java.util.List;

public class Person {

     //创建List集合属性,类型是String类型

     private List<String> list;

}

第二步编写spring的配置文件,编写bean,格式如下:

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">

     <bean name="person" class="com.yirong.bean.Person">

          <property name="list">

              <!-- 向集合中添加数据 类型是实体类规定的类型-->

              <list>

                   <value>java开发</value>

                   <value>编程设计思想</value>

              </list>

          </property>

     </bean>

</beans>

第三步写测试类,打印实体类集合属性是否有值

public static void main(String[] args) {

        //创建 Spring 的 IOC 容器

        ApplicationContext x = new ClassPathXmlApplicationContext("applicatContext2.xml");

        Person person = (Person) x.getBean("person"); //person是配置文件中bean的id

        System.out.println(person);

    }

 

集合属性,Map

  • java.util.Map 通过 <map> 标签定义, <map> 标签里可以使用多个 <entry> 作为子标签. 每个条目包含一个键和一个值.

  • 必须在 <key> 标签里定义键

  • 因为键和值的类型没有限制, 所以可以自由地为它们指定 <value>, <ref>, <bean>  <null> 元素.

  • 可以将 Map 的键和值作为 <entry> 的属性定义: 简单常量使用 key  value 来定义; Bean 引用通过 key-ref  value-ref 属性定义

第一步创建实体类:为实体类给上set,get,构造toString,方法

package com.yirong.bean;

import java.util.Map;

public class Person<T> {

     //创建map集合属性

     private Map<T, T> map;  //map是定义的属性名字,T代表泛型

}

第二步编写spring的配置文件,编写bean,格式如下:

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">

     <bean id="person" class="com.yirong.bean.Person">

          <property name="map"> <!-- map是实体类中的属性 -->

              <!-- 向集合中添加数据 类型是实体类规定的类型-->

              <map>

                   <entry key="键值对key1" value="value值1"></entry>

                   <entry key="键值对key2" value="value值2"></entry>

              </map>

          </property>

     </bean>

</beans>

第三步写测试类,打印实体类集合属性是否有值

public static void main(String[] args) {

          //使用spring方法给属性赋值

          //1.创建spring的Ioc容器 spring容器xml文件名字

          ClassPathXmlApplicationContext x = new ClassPathXmlApplicationContext("applicationContext.xml");

          //2.从bean的容器中获取bean的实例

          Person person2 = (Personx.getBean("person"); //person是配置文件中bean的id

          //3.打印实体类结果

          System.out.println(person2);

     }

集合属性,Set

第一步创建实体类:为实体类给上set,get,构造toString,方法

package com.yirong.bean;

import java.util.Set;

public class Person {

     //编写set属性

     private Set<String> set;

}

第二步编写spring的配置文件,编写bean,与list方法类似,格式如下:

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">

     <!-- 配置Person的bean -->

     <bean id="person" class="com.yirong.bean2.Person">

          <property name="set">

               <!-- 给set添加数据 -->

              <set>

                   <!-- 直接赋值 -->

                   <value>今天星期四</value>

                   <value>今天星期一</value>

                   <value>今天星期二</value>

                   <value>今天星期五</value>

              </set>

          </property>

     </bean>

</beans>

 

第三步写测试类,打印实体类集合属性是否有值,同list方法一样

集合属性,Properties

  • 使用 <props> 定义 java.util.Properties, 该标签使用多个 <prop> 作为子标签. 每个 <prop> 标签必须定义 key 属性.

 

第一步创建实体类:为实体类给上set,get,构造toString,方法

package com.yirong.bean;

import java.util.Properties;

import java.util.Set;

 

public class Person {

    //定义properties属性

   private Properties properties;

 

}

第二步编写spring的配置文件,编写bean,与list方法类似,格式如下:

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">

     <!-- 配置Person的bean -->

     <bean id="person" class="com.yirong.bean2.Person">

          <!-- 给properties属性赋值 -->

          <property name="properties">

              <!-- prop中必须定义key属性 -->

              <props>

                   <prop key="user">root</prop>

                   <prop key="password">root</prop>

                   <prop key="url">jdbc:mysql://127.0.0.1:3306/test</prop>

                   <prop key="driver">org.gjt.mm.mysql.Driver</prop>

              </props>

          </property>

     </bean>

     

</beans>

第三步写测试类,打印实体类集合属性是否有值,同上

 

集合属性,数组

第一步定义一个实体类,定义一个数组属性

private String[] arr;

第二步编写spring的配置文件,编写bean,与list方法类似,格式如下:

<!-- 配置Person的bean -->

     <bean id="person" class="com.yirong.bean2.Person">

          <!-- 给properties属性赋值 -->

          <property name="arr">

              <array>

                    <value>星期一</value>

                    <value>星期二</value>

                    <value>星期三</value>

                    <value>星期六</value>

              </array>

          </property>

     </bean>

第三步测试

//1.创建spring的Ioc容器 spring容器xml文件名字

          ClassPathXmlApplicationContext x = new ClassPathXmlApplicationContext("application.xml");

          //2.从bean的容器中获取bean的实例

          Person person2 = (Personx.getBean("person");

          //3.打印实体类结果

          System.out.println(person2);

 


7.使用 p 命名空间

创建时间:2018/7/19 9:19
更新时间:2018/7/19 14:27
作者:1876333166@qq.com

 

  • 为了简化 XML 文件的配置,越来越多的 XML 文件采用属性而非子元素配置信息。

  • Spring  2.5 版本开始引入了一个新的 p 命名空间,可以通过 <bean> 元素属性的方式配置 Bean 的属性。

  • 使用 p 命名空间后,基于 XML 的配置方式将进一步简化

  • 使用此种方式配置之前需要先导入p命名空间。方法与之前导入util命名空间类似:

  • 导入方法Spring配置文件 ----> 找到Namespaces ---> 勾选p ----> 完成

第一步编写实体类

实体类User 

package com.yirong.bean;

public class User {

     private Car car;     //Car属性定义

     private String name; //name属性定义   

}

//实体类Car

package com.yirong.bean;

public class Car {

     private String name;

}

      <!-- p引用属性赋值

          p:car-ref : 标示引用其他的bean

          p:name :标示给当然 User实体类的属性name赋值

      -->

     <bean id="user" class="com.yirong.bean.User" p:car-ref="car" p:name="张三"></bean>

     <!-- 配置Car的bean -->

     <bean id="car" class="com.yirong.bean.Car"></bean>

 


8.utility scheme 定义集合

创建时间:2018/7/19 14:27
更新时间:2018/7/19 18:25
作者:1876333166@qq.com

 

  • 使用基本的集合标签定义集合时, 不能将集合作为独立的 Bean 定义, 导致其他 Bean 无法引用该集合, 所以无法在不同 Bean 之间共享集合.

  • 可以使用 util schema 里的集合标签定义独立的集合 Bean. 需要注意的是, 必须在 <beans> 根元素里添加 util schema 定义

  • 如果想用util schema来定义集合,需要先导入util命名空间,具体方法是在配置文件编辑窗口找到Namespaces选项卡,然后加选util命令空间(打上勾表示选中)就可以了

第一步实体类定义

//属性静态常量

public static final String str = "hello";

 

第二步配置文件配置bean

<!-- <util:constant> 引用某个类型public static 域,并将其暴露为bean -->

     <util:constant static-field="com.yirong.entry.User.str" id="str" />

 

<bean id="user" class="com.yirong.entry.User">

          <constructor-arg name="map" ref="map"></constructor-arg>

          <constructor-arg name="properties" ref="properties"></constructor-arg>

     </bean>

    <!-- 供其他bean引用 -->

     <util:properties id="properties">

          <prop key="user">root</prop>

          <prop key="password">root</prop>

          <prop key="url">jdbc:mysql://localhost:3306/test</prop>

     </util:properties>

     <!-- <util:map> 创建一个java.util.map类型的bean,其中包含值或者引用  -->

     <util:map id="map">

          <entry key="key1" value="1"></entry>

          <entry key="key2" value="2"></entry>

          <entry key="key3" value="3"></entry>

          <entry key="key4" value="4"></entry>

     </util:map>

     

     <!-- <util:constant> 引用某个类型public static 域,并将其暴露为bean

          <util:list> 创建一个java.util.list类型的bean,其中包含值或者引用

          <util:properties> 创建一个java.util.properties类型的bean

          <util:property-path> 引用一个属性(或内嵌属性),并将其暴露为bean

          <util:set> 创建一个java.util.set类型的bean,其中包含值或者引用 -->

     <util:constant static-field="com.yirong.entry.User.str" id="str" />

     


9.Bean 自动装配

创建时间:2018/7/19 18:25
更新时间:2018/7/19 20:25
作者:1876333166@qq.com

 

  • Spring IOC 容器可以自动装配 Bean. 需要做的仅仅是 <bean>  autowire 属性里指定自动装配的模式

  • byType(根据类型自动装配):  IOC 容器中有多个与目标 Bean 类型一致的 Bean. 在这种情况下, Spring 将无法判定哪个 Bean 最合适该属性, 所以不能执行自动装配.

  • byName(根据名称自动装配): 必须将目标 Bean 的名称和属性名设置的完全相同.

  • constructor(通过构造器自动装配):  Bean 中存在多个构造器时, 此种自动装配方式将会很复杂. 不推荐使用

第一步创建实体类

private Car car;

private String name;

第二步配置spring文件

<!-- 自动装配 autodetect – 如果找到默认的构造函数,使用“自动装配用构造”; 否则,使用“按类型自动装配”

          1.constructor – 在构造函数参数的byType方式。

          2.byType – 按数据类型自动装配。如果一个bean的数据类型是用其它bean属性的数据类型,兼容并自动装配它。

          3.byName – 根据属性名称自动装配。如果一个bean的名称和其他bean属性的名称是一样的,将会自装配它。

          4.no – 缺省情况下,自动配置是通过“ref”属性手动设定 -->

     <!-- 使用构造自动装配 -->

     <bean id="constructor_user" class="com.yirong.auto.User" autowire="constructor">

          <constructor-arg name="name" value="小明"></constructor-arg>

     </bean>

          <bean id="car1" class="com.yirong.auto.Car"> <property name="speed" value="200"></property>

          </bean>

     <!-- 使用autowire="byType"类型自动装配 -->

     <bean id="aoto_user" class="com.yirong.auto.User" autowire="byType"></bean>

          <bean id="car1" class="com.yirong.auto.Car"> <property name="speed" value="200"></property>

          </bean>

     <!-- 使用autowire="byName"名字自动装配 -->

     <bean id="aoto_user2" class="com.yirong.auto.User" autowire="byName"></bean>

     <bean id="car" class="com.yirong.auto.Car">

          <property name="speed" value="200"></property>

     </bean>

需要注意,使用按类型装配bean方式配置的时候配置文件中该类型的bean只能有一个,否则就会出现问题


10.继承 Bean

创建时间:2018/7/19 18:52
更新时间:2018/7/20 14:13
作者:1876333166@qq.com
  • Spring 允许继承 bean 的配置, 被继承的 bean 称为父 bean. 继承这个父 Bean  Bean 称为子 Bean

  • 继承仅仅是指配置上的继承,并不意味着这两个bean之间存在继承关系。继承bean配置仅仅是为了复用其配置信息。

  •  Bean 从父 Bean 中继承配置, 包括 Bean 属性配置

  •  Bean 也可以覆盖从父 Bean 继承过来的配置

  •  Bean 可以作为配置模板, 也可以作为 Bean 实例. 若只想把父 Bean 作为模板, 可以设置 <bean> abstract 属性为true, 这样 Spring 将不会实例化这个 Bean

  • 并不是 <bean> 元素里的所有属性都会被继承. 比如: autowire, abstract .

  • 可以忽略父 Bean  class 属性, 让子 Bean 指定自己的类, 而共享相同的属性配置. 但此时 abstract 必须设为 true

<bean id="address"

    class="cn.edu.nuc.spring.beans.relation.Address"

      p:city="Beijing" p:street="WuDaokou"/>

<bean id="address2" p:street="DaZhongsi" parent="address"/>

 

<!-- 抽象beanbeanabstract属性为truebean这样的bean不能被ioc容器实例化,只能被用来继承配置。某一个beanclass属性没有指定,则该bean必须是一个抽象bean -->

<bean id="address" p:city="Beijing" p:street="WuDaokou"

      abstract="true"/>

<!-- bean配置的继承:使用beanparent属性指定继承那个bean -->

<bean id="address2" p:street="DaZhongsi" parent="address"/>

 

Bean 的作用域

  •  Spring , 可以在 <bean> 元素的 scope 属性里设置 Bean 的作用域.

  • 默认情况下, Spring 只为每个在 IOC 容器里声明的 Bean 创建唯一一个实例, 整个 IOC 容器范围内都能共享该实例所有后续的 getBean() 调用和 Bean 引用都将返回这个唯一的 Bean 实例.该作用域被称为 singleton, 它是所有 Bean 的默认作用域.

 

<bean id="car" class="cn.edu.nuc.spring.beans.scope.Car">

  <property name="brand" value="Audi"/>

  <property name="price" value="300000"/>

</bean>

public static void main(String[] args) {

  ApplicationContext ctx new ClassPathXmlApplicationContext("beans-scope.xml");

//不管调用几次都只会实例化一次,因为bean的scope属性默认是singleton单利

  Car car1 = (Car) ctx.getBean("car");

  Car car2 = (Car) ctx.getBean("car");

  System.out.println(car1 == car2);

  }

<!-- 使用beanscope属性来配置bean的作用域

singleton:默认值。容器初始化时创建bean实例,整个容器的生命周期内只创建这一个bean。单例的

prototype:原型的。容器初始化时不创建bean实例,而在每次请求时都创建一个新的bean实例,并返回。

 -->

<bean id="car" class="cn.edu.nuc.spring.beans.scope.Car"

      scope="prototype">

  <property name="brand" value="Audi"/>

  <property name="price" value="300000"/>

</bean>

 


11.使用外部属性文件

创建时间:2018/7/20 14:15
更新时间:2018/7/20 15:24
作者:1876333166@qq.com

 

 

  • 配置文件里配置 Bean , 有时需要在 Bean 的配置里混入系统部署的细节信息(例如: 文件路径, 数据源配置信息等). 而这些部署细节实际上需要和 Bean 配置相分离

  • Spring 提供了一个 PropertyPlaceholderConfigurer  BeanFactory 后置处理器, 这个处理器允许用户将 Bean 配置的部分内容外移到属性文件. 可以在 Bean配置文件里使用形式为 ${var} 的变量, PropertyPlaceholderConfigurer 从属性文件里加载属性, 并使用这些属性来替换变量.

  • Spring 还允许在属性文件中使用 ${propName},以实现属性之间的相互引用。

  • Spring 2.5 之后: 可通过 <context:property-placeholder> 元素简化:

    • <beans> 中添加 context Schema 定义

    • 在配置文件中加入如下配置:

<!-- 导入属性文件 -->

     <context:property-placeholder location="文件路径"/>

使用外部属性文件配置数据源

第一步创建配置文件

user=root

password=root

url=jdbc:mysql://localhost:3306/mysql

driverClass=com.mysql.jdbc.Driver

第二步配置数据源bean

<!-- 导入属性文件 -->

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

     <!-- 使用外部类的属性,需要导入c3p0的jar -->

     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

          <property name="user" value="${user}"></property>

          <property name="password" value="${password}"></property>

          <property name="jdbcUrl" value="${url}"></property>

          <property name="driverClass" value="${driverClass}"></property>

     </bean>

public static void main(String[] args) throws SQLException {

          ApplicationContext a = new ClassPathXmlApplicationContext("applicationContext.xml");

          <!-- 返回数据源的对象 -->

          DataSource dataSource = (DataSource) a.getBean("dataSource");

          System.out.println(dataSource.getConnection());

     }

 


12.基于注解的方式配置Bean

创建时间:2018/7/23 8:26
更新时间:2018/7/23 9:34
作者:1876333166@qq.com

 

  • 组件扫描(component scanning):  Spring 能够从 classpath 下自动扫描, 侦测和实例化具有特定注解的组件.

  • 特定组件包括:

    • @Component: 基本注解, 标识了一个受 Spring 管理的组件

    • @Respository: 标识持久层组件

    • @Service: 标识服务层(业务层)组件

    • @Controller: 标识表现层组件

  • 对于扫描到的组件, Spring 有默认的命名策略: 使用非限定类名, 第一个字母小写. 也可以在注解中通过 value 属性值标识组件的名称

当在组件类上使用了特定的注解之后, 还需要在 Spring 的配置文件中声明

<!--

        base-package 属性指定一个需要扫描的基类包Spring 容器将会扫描这个基类包里及其子包中的所有类.

        当需要扫描多个包时, 可以使用逗号分隔.

          resource-pattern :只扫描指定的包路径下的文件

      -->

     <!-- <context:component-scan base-package="com.yirong.annotation" resource-pattern="controller/*.class"></context:component-scan>

          context:include-filter :使用需要修改下面的use-default-filters参数为false默认是true

          use-default-filters="false"

     -->

     <context:component-scan base-package="com.yirong.annotation" >

          <!-- 加载不包含的目标类 -->

          <!-- <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/> -->

          <!-- 加载包含的目标类 -->

          <!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/> -->

     </context:component-scan>

实现的实体类如下:

package com.yirong.annotation;

importorg.springframework.stereotype.Component;

@Component //如果去掉注解UserRespositoryImpl类注入时会抛异常所有使用 @Autowired 注解的属性都需要被设置.  Spring 找不到匹配的 Bean 装配属性时, 会抛出异常, 若某一属性允许不被设置, 可以设置 @Autowired 注解的 required 属性为 false

public class User {

     

}

public interface UserRespository {

     void save();

}

@Repository

public class UserRespositoryImpl implements UserRespository {

 

   //注入user

     @Autowired(required=false)

     private User user;

     @Override

     public void save() {

          System.out.println("UserRespositoryImpl save....");

     }

}

public interface UserService {

     void save();

}

每个注解后面都有默认的id,类名首字母小写如果需要指定其他的类名可以如下:

@Service(value="userService")

public class UserServiceImpl implements UserService {

     @Autowired

     private UserRespository userRespository;

     

     @Override

     public void save() {

          userRespository.save();

          System.out.println("UserServiceImpl save ......");

     }

}

@Controller

public class UserController {

     @Autowired

     private UserService userService;

     

     public void save() {

          userService.save();

     }

}

  • @Autowired 注解自动装配具有兼容类型的单个 Bean属性

    • 构造器, 普通字段(即使是非 public), 一切具有参数的方法都可以应用@Autowired 注解

    • 默认情况下, 所有使用 @Autowired 注解的属性都需要被设置.  Spring 找不到匹配的 Bean 装配属性时, 会抛出异常, 若某一属性允许不被设置, 可以设置 @Autowired 注解的 required 属性为 false

    • 默认情况下,  IOC 容器里存在多个类型兼容的 Bean , 通过类型的自动装配将无法工作. 此时可以在 @Qualifier 注解里提供 Bean 的名称.Spring 允许对方法的入参标注 @Qualifier 已指定注入 Bean 的名称

    • @Autowired 注解也可以应用在数组类型的属性上, 此时 Spring 将会把所有匹配的 Bean 进行自动装配.

    • @Autowired 注解也可以应用在集合属性, 此时 Spring 读取该集合的类型信息, 然后自动装配所有与之兼容的 Bean.

    • @Autowired 注解用 java.util.Map 上时, 若该 Map 的键值为 String, 那么 Spring 将自动装配与之 Map 值类型兼容的 Bean, 此时 Bean 的名称作为键值


13.spring表达式语言:SpEL

创建时间:2018/8/2 11:36
更新时间:2018/8/2 11:41
作者:1876333166@qq.com

 

  • Spring 表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言

  • 语法类似于 ELSpEL 使用 #{…} 作为定界符,所有在大框号中的字符都将被认为是 SpEL

  • SpEL  bean 的属性进行动态赋值提供了便利

  • 通过 SpEL 可以实现:

    • 通过 bean 的 id 对 bean 进行引用

    • 调用方法以及引用对象中的属性

    • 计算表达式的值,正则表达式匹配

SpEL:字面量(了解即可,不常用)

 

  • 字面量的表示:

    • 整数:<property name="count" value="#{5}"/>

    • 小数:<property name="frequency" value="#{89.7}"/>

    • 科学计数法:<property name="capacity" value="#{1e4}"/>

    • String可以使用单引号或者双引号作为字符串的定界符<property name=“name” value="#{'Chuck'}"/>  <property name='name' value='#{"Chuck"}'/>

    • Boolean<property name="enabled" value="#{false}"/>

SpEL引用 Bean属性方法

    <!-- 配置bean容器 -->

     <bean id="car" class="com.yirong.bean.Car">

          <!-- 给Car类中的属性赋值 -->

          <property name="price" value="3000"></property>

          <property name="name" value="abcd"/>

     </bean>

     

     <!-- 配置bean容器 -->

     <bean id="user" class="com.yirong.bean.User">

          <!-- 使用Spel方法给属性赋值,类似与ref="car" -->

          <property name="car" value="#{car}"></property>

          <!-- 使用Spel表达式对属性进行赋值,单引号与双引号标示值为String类型 -->

          <property name="name" value="#{'张三'}"></property>

          <!-- 使用Spel表达式赋值,boolean 类型赋值,true,false -->

          <property name="bool" value="#{true}"></property>

          <!-- 类似与if,else判断语句 -->

          <property name="pric" value="#{car.price==3000 ? 0:1}"></property>

          <!-- car.name,取得数据是Car类中的name属性值,转换成大写 -->

          <property name="str" value="#{car.name.toUpperCase()}"></property>

     </bean>


14.IOC 容器中 Bean 的生命周期方法

创建时间:2018/8/2 11:44
更新时间:2018/8/2 14:12
作者:1876333166@qq.com

 

 

  • Spring IOC 容器可以管理 Bean 的生命周期, Spring 允许在 Bean 生命周期的特定点执行定制的任务.

  • Spring IOC 容器对 Bean 的生命周期进行管理的过程:

    • 通过构造器或工厂方法创建 Bean 实例

    •  Bean 的属性设置值和对其他 Bean 的引用

    • 调用 Bean 的初始化方法

    • Bean 可以使用了

    • 当容器关闭时, 调用 Bean 的销毁方法

  •  Bean 的声明里设置 init-method  destroy-method 属性,  Bean 指定初始化和销毁方法.

第一步创建实体类

public class Car {

  public Car() {

  System.out.println("car's constructor...");

  }

  private String brand;

  public void setBrand(String brand) {

  System.out.println("set brand...");

  this.brand = brand;

  }

  public void init() {

  System.out.println("init...");

  }

  public void destory() {

  System.out.println("destory...");

  }

}

第二步编写配置

init-method="init" bean的初始化方法,destroy-method="destory" 销毁方法

<bean id="car" class="cn.edu.nuc.spring.cycle.Car"

  init-method="init" destroy-method="destory">

  <property name="brand" value="Audi"/>

</bean>

第三步main方法测试

public static void main(String[] args) {

   ClassPathXmlApplicationContext ctx =

        new ClassPathXmlApplicationContext("beans-cycle.xml");

   Car car = (Car) ctx.getBean("car");

   System.out.println(car);

   ctx.close();  //关闭Ioc容器

    }

 


15.创建 Bean 的工厂方法

创建时间:2018/8/2 14:13
更新时间:2018/8/2 14:27
作者:1876333166@qq.com

 

  • 调用静态工厂方法创建 Bean是将对象创建的过程封装到静态方法中. 当客户端需要对象时, 只需要简单地调用静态方法, 而不同关心创建对象的细节.

  • 要声明通过静态方法创建的 Bean, 需要在 Bean 的 class 属性里指定拥有该工厂的方法的类, 同时在 factory-method 属性里指定工厂方法的名称. 最后, 使用 <constrctor-arg> 元素为该方法传递方法参数.

工厂方法分为静态工厂,与实例工厂

  • 实例工厂方法: 将对象的创建过程封装到另外一个对象实例的方法里. 当客户端需要请求对象时, 只需要简单的调用该实例方法而不需要关心对象的创建细节.

  • 要声明通过实例工厂方法创建的 Bean

    •  bean  factory-bean 属性里指定拥有该工厂方法的 Bean

    •  factory-method 属性里指定该工厂方法的名称

    • 使用 construtor-arg 元素为工厂方法传递方法参数

第一步创建静态工厂方法

/**

 * 静态工厂方法:通过静态方法返回bean的实例

 * @author Administrator

 */

public class CarFactory {

     private static Map<String, Car> map = new HashMap<String, Car>();

     static {

          map.put("car1", new Car("audi1", 1000000));

          map.put("car2", new Car("audi2", 1000000));

     }

     //静态方法

     public static Car getCar(String name) {

          return map.get(name);

     } 

}

创建实例工厂的实例

/**

 * 实例工厂方法:即需要创建工厂本身在调用工厂的实例方法,返回工厂实例

 * @author Administrator

 */

public class IntanceCarFactory {

     private Map<String, Car> map;

     public IntanceCarFactory() {

          map = new HashMap<>();

          map.put("car1", new Car("car2", 300000));

     }

     

     //实例方法

     public Car getCar(String name) {

          return map.get(name);

     } 

}

第二步配置Bean

<!-- 配置Car的bean -->

     <bean id="car" class="com.yirong.bean.Car"></bean>

     <!--

          通过静态工厂方法来配置Bean, 注意:不是配置静态方法实例,而是配置bean实例

          class属性 :指向静态工厂方法的全类名

          factory-method :指向静态工厂方法的方法名

          constructor-arg : 如果工厂方法需要传入参数,则使用constructor-arg,设置参数

      -->

     <bean id="carfactory" class="com.yirong.bean.factory.CarFactory" factory-method="getCar">

          <constructor-arg value="car2"></constructor-arg>

     </bean>

     

     <!-- 配置工厂的实例 -->

     <bean id="carfactory1" class="com.yirong.bean.factory.IntanceCarFactory"></bean>

     

     <!-- 通过实例工厂,返回工厂的实例 -->

     <bean id="car1" factory-bean="carfactory1" factory-method="getCar">

          <constructor-arg value="car1"></constructor-arg>

     </bean>

 

第三步测试方法

public static void main(String[] args) {

          ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext.xml");

          Car car = (Car) act.getBean("carfactory");

          System.out.println(car);

          Car car1 = (Car) act.getBean("car1");

          System.out.println(car1);

          Car car2 = (Car) act.getBean("carfactoryBean");

          System.out.println(car2);

     }

实现 FactoryBean 接口在 IOC 容器中配置 Bean范例

  • Spring 中有两种类型的 Bean, 一种是普通Bean, 另一种是工厂Bean, FactoryBean.

  • 工厂 Bean 跟普通Bean不同, 其返回的对象不是指定类的一个实例, 其返回的是该工厂 Bean  getObject 方法所返回的对象

/**

 * 创建factoryBean的方法,需要实现FactoryBean<Car>

 * @author Administrator

 *

 */

public class CarfactoryBean implements FactoryBean<Car>{

     private String name;

     

     public void setName(String name) {

          this.name = name;

     }

     

     //返回的对象

     @Override

     public Car getObject() throws Exception {

          return new Car(name, 5000000);

     }

     //返回对象的类型

     @Override

     public Class<?> getObjectType() {

          return Car.class;

     }

     //返回单利

     @Override

     public boolean isSingleton() {

          return true;

     }

}

配置文件

<!-- 通过FactoryBean来配置Bean的实例

          class :指向FactoryBean的全类名

          property : 配置FactoryBean的实例

          但实际返回的是FactoryBean的getObject() 方法,返回的实例

     -->

     <bean id="carfactoryBean" class="com.yirong.bean.factoryBean.CarfactoryBean">

          <property name="name" value="MBW"></property>

     </bean>


16.泛型依赖注入

创建时间:2018/8/2 14:36
更新时间:2018/8/2 14:37
作者:1876333166@qq.com

 

  • Spring 4.x 中可以为子类注入子类对应的泛型类型的成员变量的引用


17.Aop动态代理

创建时间:2018/8/2 15:27
更新时间:2018/8/2 15:44
作者:1876333166@qq.com

 

  • 代理设计模式的原理: 使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时将方法调用转到原始对象上.

第一步创建接口方法类

public interface Algorithm {

     public int add(int i,int j);

     public int aub(int i,int j);

     public int mul(int i,int j);

     public int div(int i,int j);

}

第二步创建实现类实现接口的方法

@Component(value="algorithmImpl")

public class AlgorithmImpl implements Algorithm{

     @Override

     public int add(int iint j) {

          System.out.println("这个是加法运算" + i + "+" + j);

          int result = i + j;

          System.out.println("计算结果是:" + result);

          return result;

     }

 }

第三步创建代理类

/**

 * 动态代理类,实现代理

 * @author Administrator

 */

public class CalculatorLoggingHandler {

     //代理对象

     private Algorithm target;

     

     public CalculatorLoggingHandler(Algorithm target) {

          this.target = target;

     }

     public Algorithm gettargetProxy() {

          Algorithm proxy = null;

          //代理对象由哪一个加载器类进行加载

          ClassLoader loader = target.getClass().getClassLoader();

          //代理对象的类型,其中有哪些方法

          Class [] arg1 = new Class[] {Algorithm.class};

          //当调用代理对象的类型,即执行的方法

          InvocationHandler h = new InvocationHandler() {

              /**

               * proxy : 正在代理的对象,一般不调用

               * method : 正在被调用的方法

               * arg2 : 调用时传入的参数

               *

               */

              @Override

              public Object invoke(Object proxy, Method method, Object[] arg2) throws Throwable {

                   

                   String methodName = method.getName();

                   //日志

                   System.out.println("这个是"+methodName+"运算" + Arrays.asList(arg2));

                   //执行方法

                   Object retult method.invoke(target, arg2);

                   System.out.println("这个是"+methodName+"运算计算结果是" + retult);

                   return retult;

              }

          };

          proxy = (Algorithm) Proxy.newProxyInstance(loader, arg1, h);

          return proxy;

     }

}

测试方法

public static void main(String[] args) {

          // 初始化

          Algorithm target = new AlgorithmImpl();

          //初始化代理对象

          Algorithm proxy = new CalculatorLoggingHandler(target).gettargetProxy();

          //使用代理执行方法

          int result = proxy.add(1, 5);

          System.out.println(result);

          result = proxy.div(4, 2);

          System.out.println(result);

     }

 


18.Aop切面,基于 注解的方式声明切面

创建时间:2018/8/2 15:47
更新时间:2018/8/2 16:12
作者:1876333166@qq.com

 

  • 切面(Aspect):  横切关注点(跨越应用程序多个模块的功能)被模块化的特殊对象

  • 通知(Advice):  切面必须要完成的工作

  • 目标(Target): 被通知的对象

  • 代理(Proxy): 向目标对象应用通知之后创建的对象

  • 连接点(Joinpoint):程序执行的某个特定位置:个如类某方法调用前、调用后、方法抛出异常后等连接点由两个信息确定:方法表示的程序执行点;相对点表示的方位。例如 ArithmethicCalculator#add() 方法执行前的连接点,执行点为ArithmethicCalculator#add(); 方位为该方法执行前的位置

  • 切点(pointcut):每个类都拥有多个连接点:例如 ArithmethicCalculator 的所有方法实际上都是连接点,即连接点是程序类中客观存在的事务AOP 通过切点定位到特定的连接点。类比:连接点相当于数据库中的记录,切点相当于查询条件。切点和连接点不是一对一的关系,一个切点匹配多个连接点,切点通过 org.springframework.aop.Pointcut 接口进行描述,它使用类和方法作为连接点的查询条件

  • AspectJJava 社区里最完整最流行的 AOP 框架.

  •  Spring2.0 以上版本, 可以使用基于 AspectJ 注解或基于 XML 配置的 AOP

 

在Spring中启用Aspectj注解支持

  • 要在 Spring 应用中使用 AspectJ 注解, 必须在 classpath 下包含 AspectJ 类库: aopalliance.jaraspectj.weaver.jar  spring-aspects.jar

  •  aop Schema 添加到 <beans> 根元素中.

  •  Spring IOC 容器中启用 AspectJ 注解支持, 只要 Bean 配置文件中定义一个空的 XML 元素 <aop:aspectj-autoproxy>

  •  Spring IOC 容器侦测到 Bean 配置文件中的 <aop:aspectj-autoproxy> 元素时, 会自动为与 AspectJ 切面匹配的 Bean 创建代理.

  • AspectJ 支持 5 种类型的通知注解:

    • @Before: 前置通知, 在方法执行之前执行

    • @After: 后置通知, 在方法执行之后执行

    • @AfterRunning: 返回通知, 在方法返回结果之后执行

    • @AfterThrowing: 异常通知, 在方法抛出异常之后

    • @Around: 环绕通知, 围绕着方法执行

  • 最典型的切入点表达式时根据方法的签名来匹配各种方法:

    • execution * com.atguigu.spring.ArithmeticCalculator.*(..): 匹配 ArithmeticCalculator 中声明的所有方法,第一个 * 代表任意修饰符及任意返回值. 第二个 * 代表任意方法. .. 匹配任意数量的参数. 若目标类与接口与该切面在同一个包中, 可以省略包名.

    • execution public * ArithmeticCalculator.*(..): 匹配 ArithmeticCalculator 接口的所有公有方法.

    • execution public double ArithmeticCalculator.*(..): 匹配 ArithmeticCalculator 返回 double 类型数值的方法

    • execution public double ArithmeticCalculator.*(double, ..): 匹配第一个参数为 double 类型的方法, .. 匹配任意数量任意类型的参数

    • execution public double ArithmeticCalculator.*(double, double): 匹配参数类型为 double, double 类型的方法.

 

第一步创建接口与实现类

public interface Algorithm {

     public int add(int i,int j);

     public int div(int i,int j);

}

//注解把当前AlgorithmImpl交给Spring容器进行管理

@Component

public class AlgorithmImpl implements Algorithm{

     @Override

     public int add(int iint j) {

          int result = j + j;

          return result;

     }

     @Override

     public int div(int iint j) {

          int result = i / j;

          return result;

     }

}

第二步日志文件

/**

 * 日志文件

 * @author Administrator

 */

// 把这个类声明为一个切面,需要把该类放入到Ioc容器中,在声明一个切面

@Order(1) //如果有多个日志文件可以使用order注解设置切面的优先级 数字越大优先级越高

@Aspect

@Component

public class AlgorithmLoggin {

     /**

      * 声明切入点的方法

      * 合并切入点表达式,使用注解 @Pointcut

      */

     @Pointcut("execution(* *.*(int, int))")

     private void pointCutOperation(){}

     // 在目标方法之后执行,

     @After("pointCutOperation()")

     public void afterMethod(JoinPoint joinPoint) {

          // 获取连接点的方法签名对象的名字

          String methodName = joinPoint.getSignature().getName();

          System.out.println("这个" + methodName + "方法正在结束");

     }

     // 声明该方法是一个前置通知,在目标方法之前执行JoinPoint连接点

     // execution 匹配方法执行的连接点

     @Before("pointCatOperation()")

     public void beforeMethod(JoinPoint joinPoint) {

          // 获取连接点的方法签名对象的名字

          String methodName = joinPoint.getSignature().getName();

          System.out.println("正在执行的" + methodName + "方法" + Arrays.asList(joinPoint.getArgs()));

     }

     /**

      * 执行目标方法时发生异常执行

      * @param joinPoint

      * @param e

      */

     @AfterThrowing(pointcut = "pointCatOperation()", throwing = "e")

     public void AfterThrowingMethod(JoinPoint joinPoint, Exception e) {

          // 获取连接点的方法签名对象的名字

          String methodName = joinPoint.getSignature().getName();

          System.out.println("这个是" + methodName + "方法" + "出了异常:" + e);

     }

     /**

      * 必须在通知方法的签名中添加一个同名参数. 在运行时, Spring AOP 会通过这个参数传递返回值. returning 返回参数的结果

      * @param joinPoint

      */

     @AfterReturning(pointcut = "pointCatOperation()", returning = "restult")

     public void AfterReturningMethod(JoinPoint joinPoint, Object restult) {

          // 获取连接点的方法签名对象的名字

          String methodName = joinPoint.getSignature().getName();

          System.out.println("正在执行的" + methodName + "方法" + "-----》结果是:" + restult);

     }

     /**

      * 环绕通知类似与动态代理 连接点的参数类型必须是 ProceedingJoinPoint proceed() 方法来执行被代理的方法.

      * @throws Throwable

      */

     /*

      * @Around("execution(* com.yirong.beans.aop.Algorithm.*(int, int))") public

      * Object AroundMethod(ProceedingJoinPoint joinPoin) throws Throwable {

      *

      * //执行方法 Object retult = null; try { //前置通知 System.out.println("正在执行的" +

      * joinPoin.getSignature().getName() + "方法" +

      * Arrays.asList(joinPoin.getArgs())); retult = joinPoin.proceed(); //后置通知

      * System.out.println("这个" + joinPoin.getSignature().getName() + "方法正在结束"); }

      * catch (Throwable e) { //异常通知 System.out.println("这个是" +

      * joinPoin.getSignature().getName() + "方法" + "出了异常:" + e); throw e; }

      *

      * //返回通知

      *

      * return retult; }

      */

}

第三步测试方法

public static void main(String[] args) {

          // 配置IOC容器

          ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

          // 从IOC容器中取出bean的实例

          Algorithm algorithm = applicationContext.getBean(Algorithm.class);

          // 执行对应的方法

          int result = algorithm.div(4, 2);

          System.out.println(result);

     }

第四步配置xml文件

    <!-- 配置扫描的包 -->

     <context:component-scan base-package="com.yirong.beans.aop"></context:component-scan>

     <!-- 启用 AspectJ 注解支持 -->

     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>


19.基于 XML配置声明切面

创建时间:2018/8/2 16:09
更新时间:2018/8/2 16:25
作者:1876333166@qq.com

 

第一步接口和实现类

public interface Algorithm {

     public int add(int i,int j);

     public int div(int i,int j);

}

public class AlgorithmImpl implements Algorithm{

     @Override

     public int add(int i, int j) {

          int result = j + j;

          return result;

     }

     @Override

     public int div(int i, int j) {

          int result = i / j;

          return result;

     }

}

第二步写日志类

/**

 * 日志类

 * @author Administrator

 */

public class LogginAspect {

     // 在目标方法之后执行,

     public void afterMethod(JoinPoint joinPoint) {

          // 获取连接点的方法签名对象的名字

          String methodName = joinPoint.getSignature().getName();

          System.out.println("这个" + methodName + "方法正在结束");

     }

     public void AfterThrowingMethod(JoinPoint joinPoint, Exception e) {

          // 获取连接点的方法签名对象的名字

          String methodName = joinPoint.getSignature().getName();

          System.out.println("这个是" + methodName + "方法" + "出了异常:" + e);

     }

}

第三步写XML文件

<!-- 配置实现类的bean -->

     <bean id="algorithmImpl" class="com.yirong.beansxml.aop.AlgorithmImpl"></bean>

     <!-- 配置日志类的bean -->

     <bean id="logginAspect" class="com.yirong.beansxml.aop.LogginAspect"></bean>

     <!-- 配置Aop

  • 定义在 <aop:aspect> 元素下: 只对当前切面有效

  • 定义在 <aop:config> 元素下: 对所有切面都有效

     -->

     <aop:config>

          <!-- 配置切点的表达式 -->

          <aop:pointcut expression="execution(* *.*(int, int))" id="poincut"/>

          <!-- 配置切面 -->

          <aop:aspect ref="logginAspect">

              <!-- 配置后置通知 -->

              <aop:after method="afterMethod" pointcut-ref="poincut"/>

              <aop:after-throwing method="AfterThrowingMethod" pointcut-ref="poincut" throwing="e"/>

          </aop:aspect>

     </aop:config>

第四步写测试文件

public static void main(String[] args) {

          // 配置IOC容器

          ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beansxml-aop.xml");

          // 从IOC容器中取出bean的实例

          Algorithm algorithm = (Algorithm) applicationContext.getBean("algorithmImpl");

          // 执行对应的方法

          

          int result = algorithm.div(4, 0);

          System.out.println(result);

     }

 


20.JdbcTemplate, JdbcDaoSupport 示例代码,具名参数

创建时间:2018/8/2 16:27
更新时间:2018/8/2 16:40
作者:1876333166@qq.com

 

 

  • 为了使 JDBC 更加易于使用, Spring  JDBC API 上定义了一个抽象层, 以此建立一个 JDBC 存取框架.

  • 作为 Spring JDBC 框架的核心, JDBC 模板的设计目的是为不同类型的 JDBC 操作提供模板方法. 每个模板方法都能控制整个过程, 并允许覆盖过程中的特定任务. 通过这种方式, 可以在尽可能保留灵活性的情况下, 将数据库存取的工作量降到最低.

第一步写测试类

public class TestjdbcTmplate {

     DataSource dataSource = null;

     JdbcTemplate jdbcTemplate = null;

     NamedParameterJdbcTemplate namedParameterJdbcTemplate = null;

     {

          ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-jdbctemplate.xml");

          dataSource = (DataSource) ctx.getBean("dataSource");

          jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate");

          namedParameterJdbcTemplate = (NamedParameterJdbcTemplate) ctx.getBean("namedParameterJdbcTemplate");

     }

     /**

      * 使用具名参数

      * 优点就是:当字段较多,不用考虑字段的顺序,效率高,即key,value的形式

     * 缺点:麻烦代码量多

      *

      */

     @Test

     public void testNameParter() {

          String sql = "insert into emp values(null,:b,:c,:d,:w)";

          Map<String, Object> paramMap=new HashMap<String,Object >();

        paramMap.put("b""man");

        paramMap.put("c""25");

        paramMap.put("d""18612396984");

        paramMap.put("w""18612396984");

        int update = namedParameterJdbcTemplate.update(sqlparamMap);

          System.out.println(update);

     }

     

     /**

      * 测试数据源是否连接成功

      * @throws SQLException

      */

     @Test

     public void test() throws SQLException {

          System.out.println(dataSource.getConnection());

     }

     

     /**

      * 查询实体类的集合

      * Name name 使用别名的方式

      */

     @Test

     public void testqueryForList() {

          String sql = "select id,Name name,address,age,phone from emp where id > ?";

          RowMapper<Emp> rowMapper = new BeanPropertyRowMapper<>(Emp.class);

          List<Emp> query = jdbcTemplate.query(sqlrowMapper,1);

          System.out.println(query);

     }

     

     /**

      * 查询单条记录

      * queryForObject(String sql, RowMapper<Emp> rowMapper, Object... args)

      */

     @Test

     public void testqueryForobject() {

          String sql = "select id,Name name,address,age,phone from emp where id > ?";

          RowMapper<Emp> rowMapper = new BeanPropertyRowMapper<>(Emp.class);

          Emp queryForObject = jdbcTemplate.queryForObject(sqlrowMapper, 1);

          System.out.println(queryForObject);

     }

     

     /**

      * 修改单条数据

      */

     @Test

     public void testUpdate() {

          String sql = "update emp set name = ? where id = ?";

          int result = jdbcTemplate.update(sql"lisi",1);

          System.out.println(result);

     }

     /**

      * 执行批量插入数据

      * batchArgs: 是一个集合参数,因为集合中有多个数据,所以是Object[] 数组类型

      */

     @Test

     public void testbatchUpdate() {

          String sql = "insert into emp values(?,?,?,?,?)";

          List<Object[]> batchArgs = new ArrayList<>();

          batchArgs.add(new Object[]{null,"张三",20,"广州市",10000});

          

          int[] result = jdbcTemplate.batchUpdate(sqlbatchArgs);

          System.out.println(result);

     }

     /**

      * 查询数据库中的记录总数

      * queryForObject

      */

     @Test

     public void testad() {

          String sql = "select count(*) from emp";

          int count = jdbcTemplate.queryForObject(sql,Integer.class);

          System.out.println(count);

     }

}

JDBCDaoSupper类,作用与jdbcTemplate一样,一般使用jdbcTmplate

@Repository

public class JdbcDaoSupper extends JdbcDaoSupport{

     

     /**此处必须加入dataSource或jdbcTemplate要么报错如下

     * Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required

     * 如不加jdbcTemplate。要用dataSource

     * name只能重新加入dataSource,为什么我用了setDataSource22为DataSource赋值

     * 因在JdbcDaoSupport类中为final关键字修饰,不可重写

     * @param dataSource

     */

    @Autowired

    public void  setDataSource22(DataSource dataSource) {

        setDataSource(dataSource);

    }

     public List<Emp> testqueryForList(int id){

          String sql = "select id,Name name,address,age,phone from emp where id > ?";

          RowMapper<Emp> rowMapper = new BeanPropertyRowMapper<>(Emp.class);

          return getJdbcTemplate().query(sql, rowMapper,id);

     }

}

 

第二步编写properties文件

user=root                                //root:数据库用户

password=root                            //root:数据库密码

url=jdbc:mysql://localhost:3306/user     //localhost:ip地址,localhost代表本地,3306:端口号,user:数据库名称

driverClass=com.mysql.jdbc.Driver        //musql数据库的驱动

 

第三步编写XML文件

<!-- 配置扫描的包 -->

     <context:component-scan base-package="com.yirong"></context:component-scan>

     <!-- 引入外部文件 -->

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

     

     <!-- 配置数据库的数据源 -->

     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

          <property name="user" value="${user}"></property>

          <property name="password" value="${password}"></property>

          <property name="driverClass" value="${driverClass}"></property>

          <property name="jdbcUrl" value="${url}"></property>

          <property name="testConnectionOnCheckin" value="false"/>

    <property name="testConnectionOnCheckout" value="true"/>

     </bean>

     

     <!-- 配置jdbcTemplate -->

     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">

          <property name="dataSource" ref="dataSource"></property>

     </bean>

     

     <bean id="jdbcDaoSupper" class="com.yirong.dao.JdbcDaoSupper">

          <property name="dataSource" ref="dataSource"></property>

     </bean>

     

     <!-- 配置具名参数bean -->

     <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">

          <constructor-arg name="dataSource" ref="dataSource"></constructor-arg>

     </bean>


21.Spring 中的事务管理

创建时间:2018/8/2 16:41
更新时间:2018/8/2 16:46
作者:1876333166@qq.com

 

 

 

 

 

 

 


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值