spring介绍

14 篇文章 2 订阅

 

 

01 初识Spring

1、IOC和DI是Spring的基石。
   IOC也就是控制翻转,就是把对象的创建、初始化、销毁等工作交给spring容器来做,由spring容器控制对象的生命周期。
注:如果一个系统的表结构很复杂,那么设计表的时候可以考虑分成多块进行设计,并且一个块有一个核心表,一个块和另外一个快,可以通过另外一张表建立关系。
 
 
2、使用Spring的步骤
<1>写一个java文件。
<2>写一个配置文件,这个配置文件的名字应该是applicationContext.xml,把这个类放入到Spring容器中。
<3>启动Spring容器。
<4>从Spring容器中把对象提取出来。
<5>用此对象调用相关的方法。
注:使用Spring最少需要导入两个jar表,一个是Spring的核心包,在spring的dist目录下。另外一个是第三方包commons-logging,在Spring的lib下。
HelloWorld.java
public class HelloWorld {
       public void hello(){
            System. out.println("HelloWorld" );
      }
}
 
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-2.5.xsd" >
             <!--
                  beans只要把一个java类放入到spring容器中,那么这个类就是bean
                  bean用于描述一个java类,id是唯一标示符,class代表类的全名
             -->
             <bean id ="helloWorld" class="cn.itheima.domain.HelloWorld" ></bean>
</beans>
 
HelloWorldTest.java
public class HelloWorldTest {
       @Test
       public void testHello(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
             //这里的HelloWorld就是由spring创建的
            HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld" );
            helloWorld.hello();
      }
}
 
执行结果:
HelloWorld
 
 
3、SpringIOC创建对象有三种方式:
<1>采用默认的构造函数(上面的例子就是采用默认的构造函数方式,所以如果去掉默认构造方法,那么就会报错)
<2>采用静态工厂方法
<3>采用对象工厂
 
第一种方式:采用默认的构造函数
HelloWorld.java
public class HelloWorld {
      
       public HelloWorld(){
            System. out.println("HelloWorld constructor!" );
      }
      
       public void hello(){
            System. out.println("HelloWorld" );
      }
}
 
执行结果:
HelloWorld constructor!
HelloWorld
 
 
第二种方式:采用静态工厂方法
HelloWorldFactory.java
public class HelloWorldFactory {
       public static HelloWorld getInstance(){
             return new HelloWorld();
      }
}
 
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-2.5.xsd" >
             <bean id ="helloWorld2" class="cn.itheima.domain.HelloWorldFactory" factory-method="getInstance" ></bean>
</beans>
 
HelloWorldTest.java
public class HelloWorldTest {
      
       @Test
       public void testHello(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld2" );
            helloWorld.hello();
      }
}
注:在这种由spring容器调用工厂方法而产生对象的方式,其实产生对象的逻辑还是由程序员完成的。
     在JBPM中产生各种服务正是通过工厂的形式创建的。
 
 
4、如果配置文件中配置了两次同一个类,那么这个类就会被创建两次。
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-2.5.xsd" >
             <bean id ="helloWorld1" class="cn.itheima.domain.HelloWorld" ></bean>
             <bean id ="helloWorld2" class="cn.itheima.domain.HelloWorldFactory" factory-method="getInstance" ></bean>
</beans>
 
执行结果:
HelloWorld constructor!
HelloWorld constructor!
HelloWorld
 
 
5、一个spring配置文件import另一个spring配置文件的情况
classpath路径下的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-2.5.xsd" >
             <bean id ="helloWorld2" class="cn.itheima.domain.HelloWorldFactory" factory-method="getInstance" ></bean>
             <import resource ="cn/itheima/test/applicationContext.xml" />
</beans>
 
cn/itheima/test/applicationContext.xml目录下的applicationContext:
<?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-2.5.xsd" >
             <bean id ="helloWorld1" class="cn.itheima.domain.HelloWorld" ></bean>
</beans>
 
HelloWorldTest.java
public class HelloWorldTest {
      
       @Test
       public void testHello(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld2" );
            helloWorld.hello();
      }
}
 
执行结果:
HelloWorld constructor!
HelloWorld constructor!
HelloWorld
 
 
6、用spring容器创建的一个bean类的两个对象是同一个对象。也就是说Spring容器中默认的产生对象的scope是单例的。所以,如果把一个数据声明放到该类的属性中,那么这个数据将成为全局共享的数据。
HelloWorldTest.java
public class HelloWorldTest {
      
       @Test
       public void testHello (){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld" );
            System. out.println(helloWorld);
            helloWorld = (HelloWorld)context.getBean("helloWorld");
            System. out.println(helloWorld);
      }
}
 
执行结果:
HelloWorld constructor!
cn.itheima.domain.HelloWorld@1e1dadb
cn.itheima.domain.HelloWorld@1e1dadb
 
 
7、Spring中的scope配置
* singleton 默认
* prototype 如果设置scope的属性值为此值,那么创建出来的bean对象将是多例的。
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-2.5.xsd" >
             <bean id ="helloWorld" class="cn.itheima.domain.HelloWorld" scope="prototype" ></bean>
</beans>

执行结果:
HelloWorld constructor!
cn.itheima.domain.HelloWorld@cbdb20
HelloWorld constructor!
cn.itheima.domain.HelloWorld@19f3736
注:将来spring容器和web容器整合,当web容器启动的时候,spring容器就会为bean创建对象,如果spring配置文件的bean写错了,则在web容器启动的时候就会报错,如果是在context.getBean时,才要为bean创建对象,这个时候,spring配置文件中的错误就会被隐藏掉。
 
 
8、Spring中的lazy-init配置
* false/default 在spring容器启动的时候创建对象。
* true bean会延迟创建对象,在context.getBean时才会创建。
如果一个bean已经在spring容器中了,并且该bean中需要大量的数据,这个时候,延迟加载稍微好点。
 
 
9、Spring的init和destroy方法
init-method="init",该方法是由spring容器来调用的。
destory-method="destroy",该方法也是由spring容器调用的。
当spring容器关闭的时候,或者销毁的时候,执行该方法,在该方法中可以做一些资源释放的工作。
注:spring容器管理bean的生命周期:对象的创建、初始化、销毁工作。
HelloWorld.java
public class HelloWorld {
      
       public void init(){
            System. out.println("init" );
      }
      
       public HelloWorld(){
            System. out.println("HelloWorld constructor!" );
      }
      
       public void hello(){
            System. out.println("HelloWorld" );
      }
      
       public void destroy(){
            System. out.println("destroy" );
      }
}
 
applicationContext.java
<?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-2.5.xsd" >
             <bean id ="helloWorld" class="cn.itheima.domain.HelloWorld" init-method="init" destroy-method="destroy" ></bean>
</beans>
 
HelloWorldTest.java
public class HelloWorldTest {
      
       @Test
       public void testHello (){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld" );
            System. out.println(helloWorld);
      }
}
 
执行结果:
HelloWorld constructor!
init
cn.itheima.domain.HelloWorld@e79839
 
HelloWorldTest.java
public class HelloWorldTest {
      
       @Test
       public void testHello(){
            ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml");
            HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld" );
            System. out.println(helloWorld);
             //强转为子类类型
             ClassPathXmlApplicationContext context2 = (ClassPathXmlApplicationContext)context;
             //将spring容器关闭掉,就会调用bean对象的destroy方法
             //context2.close();
            context2.destroy();
      }
}
 
执行结果:
HelloWorld constructor!
init
cn.itheima.domain.HelloWorld@e79839
destroy
 
 
10、scope为prototype的情况
这种情况,即使spring容器销毁了,但是该bean并没有销毁。例如Struts2中,action是多粒的,可以由spring创建,但是创建完之后不能由spring管理,而应该由struts2管理,所以spring容器销毁了,但是bean不能销毁。
applicationContext.java
<?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-2.5.xsd" >
             <bean id ="helloWorld" class="cn.itheima.domain.HelloWorld" init-method="init" destroy-method="destroy" scope="prototype" ></bean>
</beans>
 
执行结果:
HelloWorld constructor!
init
cn.itheima.domain.HelloWorld@cbdb20
注:如果一个bean的scope设置为prototype,那么lazy-init的属性将会失效,不管怎么样设置,都是在context.getBean时创建对象。例如:action是在请求的时候创建对象的,并不是在web容器启动的时候创建对象的。
 

11、Spring起别名功能
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-2.5.xsd" >
             <bean id ="helloWorld" class="cn.itheima.domain.HelloWorld" lazy-init="false" init-method="init" destroy-method="destroy" ></bean>
             <alias name ="helloWorld" alias="hello1" />
             <alias name ="helloWorld" alias="hello2" />
</beans>
 
HelloWorldTest.java
public class HelloWorldTest {
      
       @Test
       public void testHello(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            HelloWorld helloWorld = (HelloWorld)context.getBean("hello1" );
            System. out.println(helloWorld);
      }
}
 
执行结果:
HelloWorld constructor!
init
cn.itheima.domain.HelloWorld@bac9b9
 
 
12、Spring中的依赖注入(DI)
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-2.5.xsd" >
             <bean id ="person" class="cn.itheima.domain.Person" >
                   <property name ="pid" value="1" ></property>
             </bean>
             <bean id ="student" class="cn.itheima.domain.Student" ></bean>
</beans>
 
Person.java
public class Person {
       private Long pid ;
       private String pname ;
       private Student student ;
       private List lists ;
       private Set sets ;
       private Map maps ;
       private Properties properties ;
      
       public Person(){
            System. out.println("person init" );
      }
      
       public Long getPid() {
             return pid ;
      }
       public void setPid(Long pid) {
             this.pid = pid;
      }
       public String getPname() {
             return pname ;
      }
       public void setPname(String pname) {
             this.pname = pname;
      }
       public Student getStudent() {
             return student ;
      }
       public void setStudent(Student student) {
             this.student = student;
      }
       public List getLists() {
             return lists ;
      }
       public void setLists(List lists) {
             this.lists = lists;
      }
       public Set getSets() {
             return sets ;
      }
       public void setSets(Set sets) {
             this.sets = sets;
      }
       public Map getMaps() {
             return maps ;
      }
       public void setMaps (Map maps) {
             this.maps = maps;
      }
       public Properties getProperties() {
             return properties ;
      }
       public void setProperties(Properties properties) {
             this.properties = properties;
      }
}
 
Student.java
public class Student {
 
}
 
DITest.java
public class DITest{
      
       @Test
       public void testHello(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            Person person = (Person)context.getBean( "person");
            System. out.println(person.getPid());
            System. out.println(person.getPname());
      }
}
 
执行结果:
HelloWorld constructor!
init
1
//如果设置了该属性,那么就会有值,否则为null
null
 
 
13、属性值为引用类型的情况
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-2.5.xsd" >
             <bean id ="helloWorld" class="cn.itheima.domain.HelloWorld" lazy-init="false" init-method="init" destroy-method="destroy" ></bean>
             <bean id ="person" class="cn.itheima.domain.Person" >
                   <property name ="pid" value="1" ></property>
                   <property name ="pname" value="wq" ></property>
                   <property name ="student" >
                         <ref bean ="student" />
                   </property>
             </bean>
             <bean id ="student" class="cn.itheima.domain.Student" ></bean>
</beans>
注:从上面的配置文件可以看出,person对象对于student是具有依赖性的,所以在spring容器内部做的事情:
* 创建person对象
* 创建student对象
* 调用set方法赋值
 
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-2.5.xsd" >
             < bean id ="helloWorld" class ="cn.itheima.domain.HelloWorld" lazy-init ="false" init-method ="init" destroy-method ="destroy" ></ bean>
             < bean id ="person" class ="cn.itheima.domain.Person" >
                   < property name ="pid" value ="1" ></ property>
                   < property name ="pname" value ="wq" ></ property>
             </ bean>
             < bean id ="student" class ="cn.itheima.domain.Student" ></ bean>
</ beans>
 
注:从上面的配置可以看出,即便在类中person和student是存在依赖关系的,但是从spring容器的角度考虑,却没有建立依赖关系,所以执行顺序为:
* 创建person对象
* 调用person的set方法赋值
* 创建student对象
 
注:applicationContext.xml中,property是用来描述class中的属性,name属性的值来源于类的set方法,value就是给值的(基本类型的包装类型与String类型),ref指向spring内部的对象,引用类型用ref。
 
 
14、各种类型属性的赋值情况
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-2.5.xsd" >
             <bean id ="helloWorld" class="cn.itheima.domain.HelloWorld" lazy-init="false" init-method="init" destroy-method="destroy" ></bean>
             <bean id ="person" class="cn.itheima.domain.Person" >
                   <property name ="pid" value="1" ></property>
                   <property name ="pname" value="wq" ></property>
                   <property name ="student" >
                         <ref bean ="student" />
                   </property>
                   <property name ="lists" >
                         <list>
                               <value> list1</value >
                               <value> list2</value >
                               <ref bean ="student" />
                         </list>
                   </property>
                   <property name ="sets" >
                         <set>
                               <value> set1</value >
                               <ref bean ="student" />
                         </set>
                   </property>
                   <property name ="maps" >
                         <map>
                               <entry key ="m1" >
                                     <value> m1</ value>
                               </entry>
                               <entry key ="m2" >
                                     <ref bean ="student" />
                               </entry>
                         </map>
                   </property>
                   <property name ="properties" >
                         <props>
                               <prop key ="p1" >
                                   p1  
                               </prop>
                         </props>
                   </property>
             </bean>
             <bean id ="student" class="cn.itheima.domain.Student" ></bean>
</beans>
 
DITest.java
public class DITest{
      
       @Test
       public void testHello(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            Person person = (Person)context.getBean( "person");
            System. out.println(person.getPid());
            System. out.println(person.getPname());
            
            List lists = person.getLists();
            System. out.println(lists.size());
      }
}
 
执行结果:
uploading.4e448015.gif正在上传…重新上传取消
注:一般情况下,把list,map,set等信息封装到spring容器的配置文件中,这些集合一般都存放固定的信息。
 
 
15、Spring中指定构造方法创建对象的情况
Person.java
public class Person {
       private Long pid ;
       private String pname ;
       private Student student ;
       private List lists ;
       private Set sets ;
       private Map maps ;
       private Properties properties ;
      
       public Person(){
            System. out.println("person init" );
      }
      
       public Person(Long pid){
             this.pid = pid;
      }
      
       public Person(String pname){
             this.pname = pname;
      }
      
       public Person(String pname,Long pid){
             this.pid = pid ;
             this.pname = pname;
      }
      
       public Long getPid() {
             return pid ;
      }
       public void setPid(Long pid) {
             this.pid = pid;
      }
       public String getPname() {
             return pname ;
      }
       public void setPname(String pname) {
             this.pname = pname;
      }
       public Student getStudent() {
             return student ;
      }
       public void setStudent(Student student) {
             this.student = student;
      }
       public List getLists() {
             return lists ;
      }
       public void setLists(List lists) {
             this.lists = lists;
      }
       public Set getSets() {
             return sets ;
      }
       public void setSets(Set sets) {
             this.sets = sets;
      }
       public Map getMaps() {
             return maps ;
      }
       public void setMaps(Map maps) {
             this.maps = maps;
      }
       public Properties getProperties() {
             return properties ;
      }
       public void setProperties(Properties properties) {
             this.properties = properties;
      }
}
 
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-2.5.xsd" >
             <bean id ="person" class="cn.itheima.domain.Person" >
                   <!--
                        用来描述构造函数的参数
                        index 构造函数的参数的位置,从0开始
                        type 构造函数的类型
                        value 赋值基本类型
                        ref 赋值一个引用
                   -->
                   <constructor-arg index ="0" value="aaa" ></constructor-arg>
                   <constructor-arg index ="1" value="1" ></constructor-arg>
             </bean>
             <bean id ="student" class="cn.itheima.domain.Student" ></bean>
</beans>
 
DITest.java
public class HelloWorldTest {
      
       @Test
       public void testHello (){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            Person person = (Person)context.getBean( "person");
            System. out.println(person.getPid());
            System. out.println(person.getPname());
      }
}
 
执行结果:
1
aaa
 
 
16、利用注解完成DI
applicationContext.java
<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
             <bean id ="person" class="cn.itheima.domain.Person" ></bean>
             <bean id ="student" class="cn.itheima.domain.Student" ></bean>
             <!--
                  启动依赖注入的注解解析器
             -->
             <context:annotation-config></ context:annotation-config>
</beans>
 
Person.java
public class Person {
       private Long pid ;
       private String pname ;
       @Resource
       private Student student ;
       private List lists ;
       private Set sets ;
       private Map maps ;
       private Properties properties ;
      
       public Person(){
            System. out.println("person init" );
      }
       public Student getStudent(){
             return student ;
      }
       public Long getPid() {
             return pid ;
      }
       public String getPname() {
             return pname ;
      }
       public List getLists() {
             return lists ;
      }
       public Set getSets() {
             return sets ;
      }
       public Map getMaps() {
             return maps ;
      }
       public Properties getProperties() {
             return properties ;
      }
}
 
Student.java
public class Student {
 
       public Student(){
            System. out.println("student init" );
      }
      
       public void hello(){
            System. out.println("student" );
      }
}
 
DITest.java
public class DITest{
      
       @Test
       public void testHello(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
             Person person = (Person )context.getBean("person" );
            person.getStudent().hello();
      }
}
 
执行结果:
student init
student
 
 
17、@Resource注解的使用方法及原理总结:
* public class Person{
     @Resource
     private Student student;
}
 
* 配置文件
命名空间
xmlns:context ="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context
bean的配置
< bean id ="person" class ="cn.itheima.domain.Person" ></ bean>
< bean id ="student" class ="cn.itheima.domain.Student" ></ bean>
注解解析器
< context:annotation-config></ context:annotation-config >
 
注:Resource注解可以放在type、field、method上。
 
原理:
* 当启动Spring容器的时候因为有两个bean,所以这两个bean被实例化了。
* Spring容器会去解析
< context:annotation-config></ context:annotation-config >
* 会在纳入Spring管理的bean的范围内查找,看哪些bean的方法或者属性上添加了@Resource注解。
* 会去检查@Resource的name属性是否为"",如果为"",则会按照属性的名称和Spring的ID进行匹配,如果匹配成功,则赋值。如果匹配不成功,则会按照类型进行匹配,匹配成功,则赋值,如果不成功,则报错。如果不为"",则会按照name属性的值和Spring中的ID进行匹配,如果匹配不成功,则直接报错。
 
18、指定name的注解方式
Person.java
public class Person {
       private Long pid ;
       private String pname ;
       @Resource(name="aaa" )
       private Student student ;
       private List lists ;
       private Set sets ;
       private Map maps ;
       private Properties properties ;
      
       public Person(){
            System. out.println("person init" );
      }
       public Student getStudent(){
             return student ;
      }
       public Long getPid() {
             return pid ;
      }
       public String getPname() {
             return pname ;
      }
       public List getLists() {
             return lists ;
      }
       public Set getSets() {
             return sets ;
      }
       public Map getMaps() {
             return maps ;
      }
       public Properties getProperties() {
             return properties ;
      }
}
 
执行结果:
uploading.4e448015.gif正在上传…重新上传取消
 
applicationContext.java
<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
             <bean id ="person" class="cn.itheima.domain.Person" ></bean>
             <bean id ="aaa" class="cn.itheima.domain.Student" ></bean>
             <context:annotation-config></ context:annotation-config>
</beans>
 
执行结果:
student
 
19、@AutoWired与@Qualifier
Person.java
@Autowired
private Student student ;
注:AutoWired表示按照类型进行匹配,按照类型匹配时相当危险的。所以如果使用了这个注解,applicationContext.xml是不可以写两个类型相同的bean的。否则,就会报错。
 
applicatonContext.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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
             <bean id ="person" class="cn.itheima.domain.Person" ></bean>
             <bean id ="student" class="cn.itheima.domain.Student" ></bean>
             <bean id ="student1" class="cn.itheima.domain.Student" ></bean>
             <context:annotation-config></ context:annotation-config>
</beans>
 
执行结果:
uploading.4e448015.gif正在上传…重新上传取消
 
Person.java
@Autowired
@Qualifier(value="studen" )
private Student student ;
 
执行结果:
uploading.4e448015.gif正在上传…重新上传取消
 
Person.java
@Autowired
@Qualifier (value="student" )
private Student student ;
 
执行结果:
student
 
注:@Autowired和@Qualifier(value="student")一起作用就相当于@Resource。
 
 
20、类扫描机制(使配置文件中不再写bean配置)
@Component(value="p")
Spring就会创建<bean id="p" class="..Perosn">
@Component
Spring就会创建<bean id="person" class="..Person">
 
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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
             <context:component-scan base-package="cn.itheima.domain" ></context:component-scan>
</beans>
 
Person.java
@Component(value="person" )
public class Person {
       private Long pid ;
       private String pname ;
       @Autowired
       @Qualifier(value="student" )
       private Student student ;
       private List lists ;
       private Set sets ;
       private Map maps ;
       private Properties properties ;
      
       public Person(){
            System. out.println("person init" );
      }
       public Student getStudent(){
             return student ;
      }
       public Long getPid() {
             return pid ;
      }
       public String getPname() {
             return pname ;
      }
       public List getLists() {
             return lists ;
      }
       public Set getSets() {
             return sets ;
      }
       public Map getMaps() {
             return maps ;
      }
       public Properties getProperties() {
             return properties ;
      }
}
 
Student.java
@Component(value="student" )
public class Student {
 
       public Student(){
            System. out.println("student init" );
      }
      
       public void hello(){
            System. out.println("student" );
      }
}
 
DITest.java
public class DITest{
      
       @Test
       public void testHello (){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            Person person = (Person)context.getBean( "person");
            person.getStudent().hello();
      }
}
 
执行结果:
person init
student init
student
 
 
21、
* 下面的注释即包含了类扫描的,也包含了依赖注入的注释解析器
< context:component-scan base-package ="cn.itheima.domain" ></ context:component-scan>
* 如果想要把一个类放入到Spring容器中,则类上加一个@Component(value="*")注解
* 在属性上加@Resource(name="*")注解
 
 
22、原理
* 当启动Spring容器的时候,就去解析配置文件,找到
< context:component-scan base-package ="cn.itheima.domain" ></ context:component-scan>
* 就会去base-package指定的包及子包中查找类,看哪些类加了@Component注解。
* 按照@Component注解的匹配规则,去创建对象。
* 去对象中查找对应的@Resource(name="student")注解,按照@Resource(name="student")注解的匹配规则,给属性赋值。
 
注:xml与注解的依赖注入:
* xml写法比较复杂,但是效率比较高。
* 注解写法比较简单,但是效率比较低。
* 在xml文件中应用注解越多,效率越低。
 

 


 

02 IOC和DI的应用举例1

注:传统的Action调用Service,Service调用Dao的方式并没有完全的实现面向接口编程。
 
1、传统方式一:
Document.java
public interface Document {
       public void read();
       public void writer();
}
 
ExcelDocument.java
public class ExcelDocument implements Document {
       public void read(){
            System. out.println("excel read" );
      }
      
       public void writer(){
            System. out.println("excel writer" );
      }
}
 
PDFDocument.java
public class PDFDocument implements Document {
       public void read(){
            System. out.println("pdf read" );
      }
      
       public void writer(){
            System. out.println("pdf writer" );
      }
}
 
WordDocument.java
public class WordDocument implements Document {
       public void read(){
            System. out.println("word read" );
      }
      
       public void writer(){
            System. out.println("word writer" );
      }
}
 
DocumentTest.java
public class DocumentTest {
       @Test
       public void test (){
            Document wordDocument = new WordDocument();
            wordDocument.read();
            wordDocument.writer();
      }
}
 
执行结果:
word read
word writer
 
2、传统方式二
DocumentManager.java
public class DocumentManager {
       private Document document ;
      
       public DocumentManager(Document document){
             this.document = document;
      }
      
       public void read(){
             document.read();
      }
      
       public void writer (){
             document.writer();
      }
}
 
DocumentTest.java
public class DocumentTest {
       @Test
       public void test(){
            Document wordDocument = new WordDocument();
            DocumentManager dm = new DocumentManager(wordDocument);
            dm.read();
            dm.writer();
      }
}
 
执行结果:
word read
word writer
 
3、IOC和DI方式:
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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
         <bean id ="documentManager" class="cn.itheima.Test2.DocumentManager" >
                   <property name ="document" >
                         <ref bean ="wordDocument" />
                   </property>
         </bean>
         <bean id ="wordDocument" class="cn.itheima.Test2.WordDocument" ></bean>
         <bean id ="pdfDocument" class="cn.itheima.Test2.PDFDocument" ></bean>
         <bean id ="excelDocument" class="cn.itheima.Test2.ExcelDocument" ></bean>
</beans>
 
DocumentTest.java
public class DocumentTest {
       @Test
       public void test(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            DocumentManager dm = (DocumentManager)context.getBean("documentManager" );
            dm.read();
            dm.writer();
      }
}
 
注:IOC和DI实现了完全的面向接口编程,接口的实现类是由Spring容器来确定的。
 

 

03 IOC和DI的应用举例2

1、利用IOC和DI实现Action、Service、Dao之间的解耦
UserDao.java
public interface UserDao {
       public void saveUser();
       public void updateUser();
}
 
UserDaoImpl.java
public class UserDaoImpl implements UserDao {
 
       public void saveUser() {
            System. out.println("save user" );
      }
 
       public void updateUser() {
            System. out.println("update user" );
      }
      
}
 
UserService.java
public interface UserService {
       public void saveUser();
       public void updateUser();
}
 
UserServiceImpl.java
public class UserServiceImpl implements UserService {
 
       private UserDao userDao ;
      
       public UserDao getUserDao() {
             return userDao ;
      }
 
       public void setUserDao(UserDao userDao) {
             this.userDao = userDao;
      }
 
       public void saveUser() {
             userDao.saveUser();
      }
 
       public void updateUser() {
             userDao.updateUser();
      }
      
}
 
UserAction.java
public interface UserAction {
       public void saveUser();
       public void updateUser();
}
 
UserActionImpl.java
public class UserActionImpl implements UserAction {
 
       private UserService userService ;
      
       public UserService getUserService() {
             return userService ;
      }
 
       public void setUserService(UserService userService) {
             this.userService = userService;
      }
 
       public void saveUser() {
             userService.saveUser();
      }
 
       public void updateUser() {
             userService.updateUser();
      }
      
}
 
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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
         <bean id ="userDao" class="cn.itheima.Test3.UserDaoImpl" ></bean>
         <bean id ="userService" class="cn.itheima.Test3.UserServiceImpl" >
             <property name ="userDao" ref="userDao" ></property>
         </bean>
         <bean id ="userAction" class="cn.itheima.Test3.UserActionImpl" >
             <property name ="userService" ref="userService" ></property>
         </bean>
</beans>
 
UserTest.java
public class UserTest {
      
       @Test
       public void test(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            UserAction userAction = (UserAction)context.getBean("userAction" );
            userAction.saveUser();
            userAction.updateUser();
      }
}
 
执行结果:
save user
update user
 
2、利用注解方式实现
注:
* Spring给予注解的配置限于引用类型
* @Service、@Controller、@Repository是@Component的细化,用来表示更具体的用例。以后可能会有更强的功能,但是在Spring2.5它们与@Component功能上没有任何的区别。
applicationContext.java
<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
         <context:component-scan base-package="cn.itheima.Test3" ></context:component-scan>
</beans>
 
UserDaoImpl.java
@Repository (value="userDao")
public class UserDaoImpl implements UserDao {
 
       public void saveUser() {
            System. out.println("save user" );
      }
 
       public void updateUser() {
            System. out.println("update user" );
      }
      
}
 
UserServiceImpl.java
@Service(value="userService" )
public class UserServiceImpl implements UserService {
       @Resource(name="userDao" )
       private UserDao userDao ;
      
       public void saveUser() {
             userDao.saveUser();
      }
 
       public void updateUser() {
             userDao.updateUser();
      }
      
}
 
UserActionImpl.java
@Controller(value="userAction" )
public class UserActionImpl implements UserAction {
       @Resource(name="userService" )
       private UserService userService ;
 
       public void saveUser() {
             userService.saveUser();
      }
 
       public void updateUser() {
             userService.updateUser();
      }
      
}
 

执行结果:
save user
update user
 

 

04 Spring中的继承

4、Spring中的继承
Person.java
public class Person {
       private String s ;
 
       public String getS() {
             return s ;
      }
 
       public void setS(String s) {
             this.s = s;
      }
      
}
 
Student.java执行结果:
public class Student extends Person {
      
}
 
applicationContext.java
<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
         <bean id ="person" class="cn.itheima.domain.Person" >
             <property name ="s" value="aaa" ></property>
         </bean>
         <bean id ="student" class="cn.itheima.domain.Student" ></bean>
</beans>
 
StudentTest.java
public class HelloWorldTest {
      
       @Test
       public void testHello(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            Student student = (Student)context.getBean( "student");
            System. out.println(student.getS());
      }
}
 
执行结果:
null
 
applicationContext.java
<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
           <!--
            abstract说明Spring容器不能为该类实例化
            -->
         <bean id ="person" class="cn.itheima.domain.Person" abstract="true" >
             <property name ="s" value="aaa" ></property>
         </bean>
         <!--
            parent表示在spring容器的意义上student继承了person的属性
          -->
         <bean id ="student" class="cn.itheima.domain.Student" parent="person" ></bean>
</beans>

执行结果:
aaa
 
注:如果Person使用注解加入到Spring容器中的,但是在这里基本的类型S没有办法用Spring容器赋值,如果S属性必须用Spring容器赋值,则Person应该用XML的形式实现。
 

 

05 Spring AOP

1、实现一个切片编程案例,也就是在Dao类执行某个方法之前,开启事务,在方法结束之后,关闭事务。
传统利用模拟代理实现的方式:
Classes.java
public class Classes implements Serializable {
       private Long cid ;
       private String cname ;
       private String description ;
      
       public Long getCid() {
             return cid ;
      }
       public void setCid(Long cid) {
             this.cid = cid;
      }
       public String getCname() {
             return cname ;
      }
       public void setCname(String cname) {
             this.cname = cname;
      }
       public String getDescription() {
             return description ;
      }
       public void setDescription(String description) {
             this.description = description;
      }
}
 
Classes.hbm.xml
<?xml version ="1.0" ?>
<!DOCTYPE hibernate-mapping PUBLIC
       "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
       "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
 
<hibernate-mapping package ="cn.itheima.domain" >
       <class name ="Classes" table="classes" >
             <id name ="cid" column="cid" type="java.lang.Long" length="5" >
                   <generator class ="increment" />
             </id>
             <property name ="cname" column="cname" type="java.lang.String" />
             <property name ="description" column="description" type="java.lang.String" />
       </class>
</hibernate-mapping>
 
ClassesDao.java
public interface ClassesDao {
       public void saveClasses();
}
 
ClassesDaoImpl.java
public class ClassesDaoImpl extends HibernateUtil implements ClassesDao {
      
       public void saveClasses(){
            Session session = sessionFactory.getCurrentSession();
            Classes classes = new Classes();
            classes.setCname( "云2");
            session.save(classes);
      }
}
 
HibernateUtil.java
public class HibernateUtil {
      
       public static SessionFactory sessionFactory;
      
       static{
            Configuration conf = new Configuration();
            Configuration configure = conf.configure();
             sessionFactory = configure.buildSessionFactory();
      }
      
}
 
ClassesProxy.java
public class ClassesProxy extends HibernateUtil {
      
       private ClassesDao classesDao ;
      
       private Transaction transaction ;
      
       public ClassesProxy(ClassesDao classesDao){
             this.classesDao = classesDao;
      }
      
       public void saveClasses(){
             transaction = sessionFactory.getCurrentSession().beginTransaction();
             classesDao.saveClasses();
             transaction.commit();
      }
}
 
ClassTest.java
public class ClassesTest {
      
       @Test
       public void test (){
            ClassesDao classesDao = new ClassesDaoImpl();
            ClassesProxy proxy = new ClassesProxy(classesDao);
            proxy.saveClasses();
      }
}
 
执行结果:
Hibernate: select max(cid) from classes
Hibernate: insert into classes (cname, description, cid) values (?, ?, ?)
 
传统利用代理实现的方式:
ClassDaoInterceptor.java
public class ClassesDaoInterceptor extends HibernateUtil implements
            InvocationHandler {
      
       private Object target ;
      
       private Transaction transaction ;
      
       public ClassesDaoInterceptor(Object target) {
             this.target = target;
      }
 
       public Object invoke(Object proxy, Method method, Object[] args)
                   throws Throwable {
             transaction= sessionFactory.getCurrentSession().beginTransaction();
             method.invoke( target, args);
             transaction.commit();
             return null ;
      }
}
 
Classes.java
public class ClassesTest {
      
       @Test
       public void test(){
            Object target = new ClassesDaoImpl();
            ClassesDaoInterceptor interceptor = new ClassesDaoInterceptor(target);
            ClassesDao classesDao = (ClassesDao)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), interceptor);
            classesDao.saveClasses();
      }
}
 
执行结果:
Hibernate: select max(cid) from classes
Hibernate: insert into classes (cname, description, cid) values (?, ?, ?)
 
总结:
* 生成的代理对象的方法体的内容就是拦截器中的invoke方法体中的内容。
* 拦截器中的invoke方法什么时候被执行?当用户端调用代理对象的方法体的内容的时候进入了拦截器invoke方法,从而给method参数赋值了。
* 在拦截器中把事务的开启、提交和业务逻辑方法结合在一起。
 
 
2、实现查看工资的一个切面编程,在查看工资之前,必须
* 开启日志
* 开启安全性的框架
* 检查登陆人的权限,如果登陆人是admin就查看,如果不是admin,输出信息:对不起,您没有查看的权限
* 查看工资
 
传统利用代理实现的方式1:
 
SalaryManager.java
public interface SalaryManager {
       public void showSalary();
}
 
SalaryManagerImpl.java
public class SalaryManagerImpl implements SalaryManager {
       public void showSalary() {
            System. out.println("show salary" );
      }
}
 
Logger.java
public class Logger {
       public void logging(){
            System. out.println("logging" );
      }
}
 
Security.java
public class Security {
       public void security(){
            System. out.println("security" );
      }
}
 
Privilege.java
public class Privilege {
 
       private String access ;
 
       public String getAccess() {
             return access ;
      }
 
       public void setAccess(String access) {
             this .access = access;
      }
}
 
SalaryManagerInterceptor.java
public class SalaryManagerInterceptor implements InvocationHandler {
 
       private Object target ;
      
       private Logger logger ;
       private Security security ;
       private Privilege privilege ;
      
       public SalaryManagerInterceptor(Object target, Logger logger,
                  Security security, Privilege privilege) {
             super();
             this.target = target;
             this.logger = logger;
             this.security = security;
             this.privilege = privilege;
      }
 
       public Object invoke(Object proxy, Method method, Object[] args)
                   throws Throwable {
            Object result = null;
             this.logger .logging();
             this.security .security();
             if(this .privilege .getAccess().equals("admin")){
                  result = method.invoke( target, args);
            } else{
                  System. out.println("对不起,您没有查询工资的权限" );
            }
             return result;
      }
      
}
 
SalaryManagerTest.java
public class SalaryManagerTest {
 
       @Test
       public void test(){
            Object target = new SalaryManagerImpl();
            
            Logger logger = new Logger();
            Security security = new Security();
            Privilege privilege = new Privilege();
            privilege.setAccess( "aaa");
            SalaryManagerInterceptor interceptor = new SalaryManagerInterceptor(target,logger,security,privilege);
            SalaryManager proxy = (SalaryManager)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), interceptor);
            proxy.showSalary();
      }
}
 
执行结果:
logging
security
对不起,您没有查询工资的权限
 
传统利用代理实现的方式2:
Interceptor.java
public interface Interceptor {
       public void interceptor();
}
 
Logger.java
public class Logger implements Interceptor{
 
       public void interceptor() {
            System. out.println("logging" );
      }
      
}
 
Privilege.java
public class Privilege implements Interceptor {
 
       public void interceptor(){
            System. out.println("privilege" );
      }
}
 
Security.java
public class Security implements Interceptor {
      
       public void interceptor() {
            System. out.println("security" );
      }
}
 
ProxyInterceptor.java
public class ProxyInterceptor implements InvocationHandler {
 
       private Object target ;
       private List<Interceptor> interceptors ;
      
       public ProxyInterceptor(Object target, List<Interceptor> interceptors) {
             super();
             this.target = target;
             this.interceptors = interceptors;
      }
 
       public Object invoke(Object proxy, Method method, Object[] args)
                   throws Throwable {
             for(Interceptor interceptor : interceptors ){
                  interceptor.interceptor();
            }
            method.invoke( this.target , args);
             return null ;
      }
 
}
 
SalaryTest.java
public class SalaryTest {
      
       @Test
       public void test(){
            Object target = new SalaryManagerImpl();
            Privilege privilege = new Privilege();
            Security security = new Security();
            Logger logger = new Logger();
            List<Interceptor> interceptors = new ArrayList<Interceptor>();     
            interceptors.add(logger);
            interceptors.add(security);
            interceptors.add(privilege);
            ProxyInterceptor interceptor = new ProxyInterceptor(target,interceptors);
            SalaryManager proxy = (SalaryManager)Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),interceptor);
            proxy.showSalary();
      }
}
 
执行结果:
logging
security
privilege
show salary
 
 
3、通过cglib实现
ClassesDaoInterceptor.java
public class ClassesDaoInterceptor extends HibernateUtil implements
            MethodInterceptor {
      
       private Object target ;
       private Transaction transaction ;
      
       public ClassesDaoInterceptor(Object target) {
             this.target = target;
      }
 
       public Object createProxy(){
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass( this.target .getClass());
            enhancer. setCallback(this); //设置拦截器
             return enhancer.create();
      }
      
       public Object intercept(Object arg0, Method method, Object[] arg2,
                  MethodProxy arg3) throws Throwable {
             this.transaction = sessionFactory.getCurrentSession().beginTransaction();
            method.invoke( target, arg2);
             this.transaction .commit();
             return null ;
      }
}
 
ClassesTest.java
public class ClassesTest {
      
       @Test
       public void test(){
            Object target = new ClassesDaoImpl();
            ClassesDaoInterceptor interceptor = new ClassesDaoInterceptor(target);
            ClassesDao classesDao = (ClassesDao)interceptor.createProxy();
            classesDao.saveClasses();
      }
}
 
 
4、Spring AOP的一些概念
切面就是切入到其他事物中的类,例如上面的Logger、Privilege、Security等。
切面中的方法就叫做通知。
代理中的方法就称之为连接点。正是通过代理中的方法才将通知和目标方法连接到一起。例如上面的proxy.showSalary();
只有满足切入点表达式才要把通知和目标方法结合在一起。例如上面的this.privilege.getAccess().equals("admin")等。
织入:形成代理对象方法体的过程。
注:
<1>代理对象的方法和目标对象的方法和接口中的方法的名称都一样。
<2>代理对象的方法=拦截器中invoke方法体中的内容。
<3>连接点是代理对象其中的一个方法。
<4>我们可以把除了目标类以外的类都看做切面,把以外的类中的方法看做通知。
uploading.4e448015.gif正在上传…重新上传取消
 
uploading.4e448015.gif正在上传…重新上传取消
uploading.4e448015.gif正在上传…重新上传取消
 
 
5、Spring AOP编程
ClassesDaoImpl.java
public class ClassesDaoImpl extends HibernateUtil implements ClassesDao {
      
       public void saveClasses(){
             Classes classes = new Classes ();
             classes.setCname( "dfafda");
             sessionFactory.getCurrentSession().save(classes);
      }
}
 
MyTransaction.java
public class MyTransaction extends HibernateUtil {
       private Transaction transaction ;
      
       public void beginTransaction(){
             this.transaction = sessionFactory.getCurrentSession().beginTransaction ();
      }
      
       public void commit(){
             this.transaction .commit();
      }
}
 
applicationContext.java
<beans xmlns ="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" >
 
             <!-- 目标类 -->
       <bean id ="classesDao" class="cn.itheima.proxy.ClassesDaoImpl" ></bean>
             <!-- 切面 -->
         <bean id ="transaction" class="cn.itheima.proxy.MyTransaction" ></bean>
        
         <!--
                  aop的配置,配置目标类和切面
          -->
          <aop:config>
             <!-- 切入点表达式,expression,id就是该切入点表达式的唯一的标示 -->
             <aop:pointcut expression ="execution(* cn.itheima.proxy.ClassesDaoImpl.*(..))" id ="perform" />
             <!-- ref指向切面类 -->
             <aop:aspect ref ="transaction" >
                   <aop:before method ="beginTransaction" pointcut-ref="perform" />
                   <aop:after-returning method ="commit" pointcut-ref="perform" />
             </aop:aspect>
          </aop:config>
</beans>
 
ClassesProxyTest.java
public class ClassesProxyTest {
       @Test
       public void testProxy(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            ClassesDao classesDao = (ClassesDao)context.getBean("classesDao" );
            classesDao.saveClasses();
      }
}
 
执行结果:
Hibernate: select max(cid) from classes
Hibernate: insert into classes (cname, description, cid) values (?, ?, ?)
 
 
6、Spring aop的五种通知:
前置通知、后置通知、异常通知、最终通知、环绕通知
ClassesDao.java
public interface ClassesDao {
       public String saveClasses();
}
 
ClassesDaoImpl.java
public class ClassesDaoImpl extends HibernateUtil implements ClassesDao {
      
       public String saveClasses(){
            Classes classes = new Classes();
            classes.setCname( "dfafda");
             sessionFactory.getCurrentSession(). save(classes);
             return "transaction" ;
      }
}
 
MyTransaction.java
public class MyTransaction extends HibernateUtil {
       private Transaction transaction ;
      
       public void beginTransaction(){
             this.transaction = sessionFactory.getCurrentSession().beginTransaction();
      }
      
       public void commit(Object val){
            System. out.println(val.toString());
             this.transaction .commit();
      }
}
 
applicationContext.xml
<beans xmlns ="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" >
 
       <bean id ="classesDao" class="cn.itheima.proxy.ClassesDaoImpl" ></bean>
         <bean id ="transaction" class="cn.itheima.proxy.MyTransaction" ></bean>
        
          <aop:config>
             <aop:pointcut expression ="execution(* cn.itheima.proxy.ClassesDaoImpl.*(..))" id ="perform" />
             <aop:aspect ref ="transaction" >
                   <aop:before method ="beginTransaction" pointcut-ref="perform" />
                   <!--
                        returning 获取目标方法的返回值
                        在目标方法遇到异常后,后置通知就不执行了
                   -->
                   <aop:after-returning method ="commit" pointcut-ref="perform" returning="val" />
             </aop:aspect>
          </aop:config>
</beans>
 
执行结果:
Hibernate: select max(cid) from classes
transaction
Hibernate: insert into classes (cname, description, cid) values (?, ?, ?)
 
 
7、执行过程中遇到异常,则后置通知不执行
ClassesDaoImpl.java
public class ClassesDaoImpl extends HibernateUtil implements ClassesDao {
      
       public String saveClasses(){
            Classes classes = new Classes();
            classes.setCname( "dfafda");
             int a = 1/0;
             sessionFactory.getCurrentSession().save(classes);
             return "transaction" ;
      }
}
 
MyTransaction.java
public class MyTransaction extends HibernateUtil {
       private Transaction transaction ;
      
       public void beginTransaction(){
             this.transaction = sessionFactory.getCurrentSession().beginTransaction();
      }
      
       public void commit(Object val){
            System. out.println(val.toString());
             this.transaction .commit();
      }
      
       public void finallyMethod(){
            System. out.println("finally" );
      }
}
 
applicationContext.java
<beans xmlns ="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" >
 
       <bean id ="classesDao" class="cn.itheima.proxy.ClassesDaoImpl" ></bean>
         <bean id ="transaction" class="cn.itheima.proxy.MyTransaction" ></bean>
        
          <aop:config>
             <aop:pointcut expression ="execution(* cn.itheima.proxy.ClassesDaoImpl.*(..))" id ="perform" />
             <aop:aspect ref ="transaction" >
                   <aop:before method ="beginTransaction" pointcut-ref="perform" />
                   <aop:after-returning method ="commit" pointcut-ref="perform" returning="val" />
                   <!--
                        最终通知
                        无论目标方法是否遇到异常,都执行,做一些资源的释放工作
                   -->
                   <aop:after method ="finallyMethod" pointcut-ref="perform" />
             </aop:aspect>
          </aop:config>
</beans>
 
执行结果:
finally
 
 
8、环绕通知
ClassesDaoImpl.java
public class ClassesDaoImpl extends HibernateUtil implements ClassesDao {
      
       public String saveClasses(){
            Classes classes = new Classes();
            classes.setCname( "dfafda" );
            System. out .println("target class" );
             return "transaction" ;
      }
}
 
MyTransaction.java
public class MyTransaction extends HibernateUtil {
       private Transaction transaction ;
      
       /**
       * 可以从joinPoint得到目标方法的一些信息
       */
       public void beginTransaction(JoinPoint joinPoint){
            joinPoint.getArgs();
            joinPoint.getSignature();
            joinPoint.getSignature().getModifiers();
            System. out.println("adfadfafa" );
             this.transaction = sessionFactory.getCurrentSession().beginTransaction();
      }
      
       public void commit(Object val){
            System. out.println(val.toString());
             this.transaction .commit();
      }
      
       public void finallyMethod(){
            System. out.println("finally" );
      }
      
       /**
       * 如果不传jointPoint,并且执行joinPoint.proceed(),那么目标方法就不会执行
       */
       public void aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
            joinPoint.proceed();
            System. out.println("around method" );
      }
}
 
applicationContext.java
<beans xmlns ="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" >
 
       <bean id ="classesDao" class="cn.itheima.proxy.ClassesDaoImpl" ></bean>
         <bean id ="transaction" class="cn.itheima.proxy.MyTransaction" ></bean>
        
          <aop:config>
             <aop:pointcut expression ="execution(* cn.itheima.proxy.ClassesDaoImpl.*(..))" id ="perform" />
             <aop:aspect ref ="transaction" >
                   <aop:before method ="beginTransaction" pointcut-ref="perform" />
                   <aop:after-returning method ="commit" pointcut-ref="perform" returning="val" />
 
                   <aop:after method ="finallyMethod" pointcut-ref="perform" />
                  
                   <!-- 环绕通知 -->
                   <aop:around method ="aroundMethod" pointcut-ref="perform" />
             </aop:aspect>
          </aop:config>
</beans>
 
执行结果:
adfadfafa
target class
transaction
finally
around method
 
注:前置通知和后置通知可以在目标方法之前和之后做一些操作,但是不能控制目标方法的执行,环绕通知能够控制目标方法的执行。
虽然可以控制,但是在实际的项目开发过程中,控制很难。
 
 
9、异常通知
uploading.4e448015.gif正在上传…重新上传取消
 
UserDao.java
public interface UserDao {
       public void saveUser() throws Exception;
}
 
UserDaoImpl.java
public class UserDaoImpl implements UserDao {
 
       public void saveUser() throws Exception {
             int a = 1/0;
      }
 
}
 
UserService.java
public interface UserService {
       public void saveUser() throws Exception;
}
 
UserServiceImpl.java
public class UserServiceImpl implements UserService {
       private UserDao userDao ;
      
       public UserDao getUserDao() {
             return userDao ;
      }
 
       public void setUserDao(UserDao userDao) {
             this.userDao = userDao;
      }
 
       public void saveUser() throws Exception {
             userDao.saveUser();
      }
 
}
 
UserAction.java
public interface UserAction {
       public void saveUser() throws Exception;
}
 
UserActionImpl.java
public class UserActionImpl implements UserAction {
      
       private UserService userService ;
      
       public UserService getUserService() {
             return userService ;
      }
 
       public void setUserService(UserService userService) {
             this.userService = userService;
      }
 
       public void saveUser() throws Exception {
             userService.saveUser();
      }
 
}
 
MyException.java
public class MyException {
       public void myException(Throwable ex ){
            System. out.println(ex.getMessage());
      }
}
 
applicationContext.java
<beans xmlns ="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" >
 
       <bean id ="userDao" class="cn.itheima.exception.UserDaoImpl" ></bean>
         <bean id ="userService" class="cn.itheima.exception.UserServiceImpl" >
             <property name ="userDao" >
                   <ref bean ="userDao" />
             </property>
         </bean>
         <bean id ="userAction" class="cn.itheima.exception.UserActionImpl" >
             <property name ="userService" >
                   <ref bean ="userService" />
             </property>
         </bean>
        
         <bean name ="myException" class="cn.itheima.exception.MyException" ></bean>
        
          <aop:config>
             <aop:pointcut expression ="execution(* cn.itheima.exception.UserServiceImpl.*(..))" id ="perform" />
             <aop:aspect ref ="myException" >
                   <!--
                        throwing属性的值就是接受目标方法抛出的异常
                   -->
                   <aop:after-throwing method ="myException" pointcut-ref="perform" throwing="ex" />
             </aop:aspect>
          </aop:config>
</beans>
 
ExceptionTest.java
public class ExceptionTest {
       @Test
       public void testException() throws Exception{
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            UserAction userAction = (UserAction)context.getBean("userAction" );
            userAction.saveUser();
      }
}
 
执行结果:
/ by zero
 
注:在Spring中,生成代理到底是采用jdk代理还是cglib生成代理是由这个类有没有接口决定的。如果一个类有接口,那么就用jdk代理方式生成代理,如果没有接口,那么就采用cglib生成代理。
 
 
10、用Spring aop实现前面的案例
Logger.java
public class Logger {
 
       public void logging () {
            System. out.println("logging" );
      }
      
}
 
Security.java
public class Security {
      
       public void security () {
            System. out.println("security" );
      }
}
 
Privilege.java 
public class Privilege {
      
       private String access ;
      
       public String getAccess(){
             return access ;
      }
 
       public void setAccess(String access) {
             this.access = access;
      }
      
       public void checkAccess(ProceedingJoinPoint joinPoint) throws Throwable {
             if(this .access .equals("admin")){
                  joinPoint.proceed();
            } else{
                  System. out.println("没有权限" );
            }
      }
}
 
applicationContext.java
<beans xmlns ="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" >
 
       <bean id ="salaryManager" class="cn.itheima.proxy.SalaryManagerImpl" ></bean>
      
       <bean id ="privilege" class="cn.itheima.proxy.Privilege" >
             <property name ="access" value="admin" ></property>
       </bean>
      
       <bean id ="logger" class="cn.itheima.proxy.Logger" ></bean>
      
       <bean id ="security" class="cn.itheima.proxy.Security" ></bean>
      
       <aop:config>
             <aop:pointcut expression ="execution(* cn.itheima.proxy.SalaryManager.*(..))" id ="perform" />
            
             <aop:aspect ref ="logger" >
                   <aop:before method ="logging" pointcut-ref="perform" />
             </aop:aspect>
             <aop:aspect ref ="security" >
                   <aop:before method ="security" pointcut-ref="perform" />
             </aop:aspect>
             <aop:aspect ref ="privilege" >
                   <aop:around method ="checkAccess" pointcut-ref="perform" />
             </aop:aspect>
       </aop:config>
</beans>
 
SalaryTest.java
public class SalaryTest {
      
       @Test
       public void test(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml" );
            SalaryManager salaryManager = (SalaryManager)applicationContext.getBean("salaryManager" );
             salaryManager.showSalary();
      }
}
 
注:切面的执行顺序是按照它们的声明顺序执行的。
 
 
11、通过注解方式实现以上操作
ClassesDaoImpl.java
@Repository(value="classesDao" )
public class ClassesDaoImpl extends HibernateUtil implements ClassesDao {
      
       public String saveClasses(){
            Classes classes = new Classes();
            classes.setCname( "dfafda");
             System.out.println( "target class");
             sessionFactory.getCurrentSession().save(classes);
             return "transaction" ;
      }
}
 
MyTransaction.java
@Component(value="myTransaction" )
@Aspect
public class MyTransaction extends HibernateUtil {
       private Transaction transaction ;
      
       @Pointcut(value="execution(* cn.itheima.proxy.ClassesDaoImpl.*(..))")
       private void aa(){}//方法签名
      
       @Before(value="aa()" )
       public void beginTransaction (){
             this.transaction = sessionFactory.getCurrentSession().beginTransaction();
      }
      
       @AfterReturning(value="aa()" ,returning="val")
       public void commit(Object val){
            System. out.println(val.toString());
             this.transaction .commit();
      }
      
       public void finallyMethod(){
            System. out.println("finally" );
      }
      
       public void aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
            joinPoint.proceed();
            System. out.println("around method" );
      }
}
 
applicationContext.xml
<beans xmlns ="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xmlns:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-2.5.xsd" >
       <!--
            启动类扫描的注解解析器
            启动AOP的注解解析器
       -->
       <context:component-scan base-package="cn.itheima.proxy" ></context:component-scan>
    <aop:aspectj-autoproxy ></aop:aspectj-autoproxy>
</beans>
 
ClassesProxyTest.java
public class ClassesProxyTest {
       @Test
       public void testProxy(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            ClassesDao classesDao = (ClassesDao)context.getBean("classesDao" );
            classesDao.saveClasses();
      }
}
注:
<1>JavaAssist包用于实现hibernate的懒加载。
<2>代理对象的方法=目标方法+通知
<3>由于ActionProxy是Struts2容器自带的,所以在Spring的AOP中,目标类不能是action。
 

 

06 Spring与JDBC编程

1、Spring中配置以及获取数据源:
uploading.4e448015.gif正在上传…重新上传取消
 
jdbc.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc\:mysql\://localhost\:3306/myhibernate
jdbc.username=root
jdbc.password=sorry
 
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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
      
        <!--
            引入properties
            下面的bean并没有id,因为不想让客户端拿到bean对象
         -->
             <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
                <property name ="locations" >
                    <value> classpath:jdbc.properties</value >
                </property>
             </bean>
 
             <bean id ="dataSource" destroy-method="close"
                  class="org.apache.commons.dbcp.BasicDataSource" >
                <property name ="driverClassName" value="${jdbc.driverClassName}" />
                <property name ="url" value="${jdbc.url}" />
                <property name ="username" value="${jdbc.username}" />
                <property name ="password" value="${jdbc.password}" />
             </bean>
 
</beans>
 
DataSourceTest.java
public class DataSourceTest {
       @Test
       public void testDataSource(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            DataSource dataSource = (DataSource)context.getBean("dataSource" );
            System. out.println(dataSource);
      }
}
 
执行结果:
org.apache.commons.dbcp.BasicDataSource@177b3cd
 
 
2、Spring提供的jdbcTemplate范例
ClassesDao.java
public class ClassesDao extends JdbcTemplate {
       public void saveClasses(){
             this.execute("insert into classes values(21,'aa','aa')" );
      }
}
 
applicationContext.java 
<bean id ="classesDao" class="cn.itheima.jdbc.ClassesDao" >
    <property name="dataSource" >
      <ref bean="dataSource" />
    </property >
</bean>
 
ClassesTest.java
public class ClassesTest {
       @Test
       public void testSaveClasses (){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            ClassesDao classesDao = (ClassesDao)context.getBean("classesDao" );
            classesDao.saveClasses();
      }
}
 
 
3、Spring与JDBC结合
模板编程就是固定的处理方法+可变参数
uploading.4e448015.gif正在上传…重新上传取消
几种使用spring的jdbcTemplate进行dao操作的方法:
方法1:
ClassesDao2.java
public class ClassesDao2 extends JdbcDaoSupport {
       public void saveClasses(){
             this.getJdbcTemplate().execute("insert into classes values(22,'aa','aa')");
      }
}
 
applicationContext.java 
<bean id ="classesDao2" class="cn.itheima.jdbc.ClassesDao2" >
    <property name="dataSource" >
      <ref bean="dataSource" />
    </property >
</bean>
 
ClassesTest.java 
public class ClassesTest {
       @Test
       public void testSaveClasses (){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            ClassesDao2 classesDao = (ClassesDao2)context.getBean("classesDao2" );
            classesDao.saveClasses();
      }
}
 
方法2:
ClassesDao3.java
public class ClassesDao3 {
       private JdbcTemplate jdbcTemplate ;
 
       public JdbcTemplate getJdbcTemplate() {
             return jdbcTemplate ;
      }
 
       public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
             this.jdbcTemplate = jdbcTemplate;
      }
      
       public void saveClasses(){
             this.getJdbcTemplate().execute("insert into classes values(23,'aa','aa')");
      }
}
 
applicationContext.java
<bean id ="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
    <property name="dataSource" >
      <ref bean="dataSource" />
    </property >
</bean>
 
<bean id ="classesDao3" class="cn.itheima.jdbc.ClassesDao3" >
    <property name="jdbcTemplate" >
      <ref bean="jdbcTemplate" />
    </property >
</bean>
 
ClassesTest.java
public class ClassesTest {
       @Test
       public void testSaveClasses (){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            ClassesDao3 classesDao = (ClassesDao3)context.getBean("classesDao3" );
            classesDao.saveClasses();
      }
}
 
方法3:
ClassesDao4.java 
public class ClassesDao4 extends JdbcTemplate {
      
       public ClassesDao4(DataSource dataSource){
             super(dataSource);
      }
      
       public void saveClasses(){
             this.execute("insert into classes values(24,'aa','aa')" );
      }
}
 
applicationContext.java 
<bean id ="classesDao4" class="cn.itheima.jdbc.ClassesDao4" >
    <constructor-arg index="0" ref="dataSource" ></constructor-arg>
</bean>
 
ClassesTest.java
public class ClassesTest {
       @Test
       public void testSaveClasses (){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            ClassesDao4 classesDao = (ClassesDao4)context.getBean("classesDao4" );
            classesDao.saveClasses();
      }
}
 
 
 
4、Spring不但为jdbc提供了accessor、template、daoDupportor类,也为hibernate、toplink、jdo提供了类似的类。

 
5、自己写一个能够与Spring无缝结合的Template及DaoSupport
HMTemplate.java
public class HMTemplate {
       private DataSource dataSource ;
 
       public DataSource getDataSource() {
             return dataSource ;
      }
 
       public void setDataSource(DataSource dataSource) {
             this.dataSource = dataSource;
      }
      
       public HMTemplate(DataSource dataSource){
             this.dataSource = dataSource;
      }
      
       public void saveClasses(String sql ){
            Connection connection;
             try{
                  connection = this.dataSource .getConnection();
                  Statement statement = connection.createStatement();
                  statement.executeUpdate( sql);
            } catch(SQLException e){
                  e.printStackTrace();
            }
      }
}
 
HMDaoSupport.java
public class HMDaoSupport {
      
       private HMTemplate hmTemplate ;
 
       public HMTemplate getHMTemplate(){
             return hmTemplate ;
      }
      
       public HMDaoSupport(DataSource dataSource) {
             this.hmTemplate = new HMTemplate( dataSource);
      }
      
}
 
HMDao.java
public class HMDao extends HMDaoSupport {
      
       public HMDao(DataSource dataSource) {
             super(dataSource);
      }
 
       public void saveClasses(){
             this.getHMTemplate().saveClasses("insert into classes values(26,'aa','aa')");
      }
}
 
 
 
applicationContext.java
<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
      
             <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
                <property name ="locations" >
                    <value> classpath:jdbc.properties</value >
                </property>
             </bean>
 
             <bean id ="dataSource" destroy-method="close"
                  class="org.apache.commons.dbcp.BasicDataSource" >
                <property name ="driverClassName" value="${jdbc.driverClassName}" />
                <property name ="url" value="${jdbc.url}" />
                <property name ="username" value="${jdbc.username}" />
                <property name ="password" value="${jdbc.password}" />
             </bean>
            
             <bean id ="hmDao" class="cn.itheima.jdbc.HMDao" >
                <constructor-arg index ="0" ref="dataSource" ></constructor-arg>
             </bean>
</beans>
 
ClassesTest.java
public class ClassesTest {
       @Test
       public void testSaveClasses(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            HMDao classesDao = (HMDao)context.getBean( "hmDao");
            classesDao.saveClasses();
      }
}
 
 
6、深入应用JdbcTemplate
ClassesRowMapper.java 
public class ClassesRowMapper implements RowMapper{
 
       public Object mapRow(ResultSet rs, int row) throws SQLException {
            Classes classes = new Classes();
            classes.setCid(rs.getLong( "cid"));
            classes.setCname(rs.getString( "cname"));
            classes.setDescription(rs.getString( "description"));
             return classes;
      }
}
 
ClassesDao5.java 
public class ClassesDao5 extends JdbcTemplate {
      
       public List<Classes> getClassesList(){
             return this .query("select * from classes", new ClassesRowMapper());
      }
}
 
applicationContext.java
<bean id ="classesDao5" class="cn.itheima.jdbc.ClassesDao5" >
    <property name="dataSource" >
      <ref bean="dataSource" />
    </property >
</bean>
 
ClassesTest.java
public class ClassesTest {
       @Test
       public void testSaveClasses(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            ClassesDao5 classesDao = (ClassesDao5)context.getBean("classesDao5" );
             int size = classesDao.getClassesList().size();
            System. out.println(size);
      }
}
 
 
7、JdbcTemplate内部原理图
uploading.4e448015.gif正在上传…重新上传取消
 
 

 

07 Spring声明式事务处理

1、Spring声明式事务处理 
目标:程序员不再关注事务了
<1>Spring容器来管理事务:作为一个切面(相当于通知)
<2>声明的概念就是程序员告诉Spring容器目标方法应该采取什么样的事务操作
<3>数据库的CRUD操作就是程序员做的事情(相当于目标方法)
注:配置的顺序
aop的配置、切面、dao、service(目标类是service层的类)
 
 
2、Spring中的事务操作是由transactionManager进行处理的,但是不同的持久层开启transaction的方式是不同的,所以Spring中的transactionManager类并没有实现doGetTransaction方法,而是留给继承类去实现。
uploading.4e448015.gif正在上传…重新上传取消
uploading.4e448015.gif正在上传…重新上传取消
注:事务的传播属性
Required:业务方法需要在一个事务中运行,如果方法运行时,已经处在一个事务中,那么加入到该事务,否则为自己创建一个新的事务。
Requiresney:属性表明不管是否存在事务,业务方法总会为自己发起一个新的事务,如果方法已经运行在一个事务中,则原有事务会被挂起,新的事务会被创建,直到方法执行结束,新事务才算结束,原有的事务才会恢复执行。
 
 
3、下面实现对某些方法加上spring的事务
ClassesDao.java
public interface ClassesDao {
       public void saveClasses();
}
 
ClassesDaoImpl.java
public class ClassesDaoImpl extends JdbcDaoSupport implements ClassesDao{
 
       public void saveClasses() {
             this.getJdbcTemplate().execute("insert into classes values(27,'aa','aa')");
      }
      
}
 
ClassesService.java
public interface ClassesService {
       public void saveClasses();
}
 
ClassesServiceImpl.java
public class ClassesServiceImpl implements ClassesService {
 
       private ClassesDao classesDao ;
      
       public ClassesDao getClassesDao() {
             return classesDao ;
      }
 
       public void setClassesDao(ClassesDao classesDao) {
             this.classesDao = classesDao;
      }
 
       public void saveClasses() {
             classesDao.saveClasses();
             int a = 1/0;
             classesDao.saveClasses();
      }
 
}
 
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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
      
             <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
                <property name ="locations" >
                    <value> classpath:jdbc.properties</value >
                </property>
             </bean>
 
             <bean id ="dataSource" destroy-method="close"
                  class="org.apache.commons.dbcp.BasicDataSource" >
                <property name ="driverClassName" value="${jdbc.driverClassName}" />
                <property name ="url" value="${jdbc.url}" />
                <property name ="username" value="${jdbc.username}" />
                <property name ="password" value="${jdbc.password}" />
             </bean>
            
             <bean id ="classesDao" class="cn.itheima.jdbc.ClassesDaoImpl" >
                <property name ="dataSource" >
                   <ref bean ="dataSource" />
                </property>
             </bean>
            
             <bean id ="classesService" class="cn.itheima.jdbc.ClassesServiceImpl" >
                <property name ="classesDao" >
                   <ref bean ="classesDao" />
                </property>
             </bean>
            
             <bean id ="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
                   <property name ="dataSource" >
                         <ref bean ="dataSource" />
                   </property>
             </bean>
            
             <!--
                  通知
                  transaction-manager 事务管理器,告诉spring容器用什么技术来启动事务
             -->
             <tx:advice transaction-manager ="transactionManager" id= "tx">
                   <tx:attributes>
                         <!--
                              name:方法的名称 save*
                              propagation:在一个方法中,调用了好几个方法,而这几个方法中还存在事务,怎么样保证所有的方法在一个事务下运行
                              read-only:true 只读事务 false 读写事务
                         -->
                         <tx:method name ="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
                   </tx:attributes>
             </tx:advice>
            
             <!-- aop的配置 -->
             <aop:config>
                   <aop:pointcut expression ="execution(* cn.itheima.jdbc.ClassesServiceImpl.*(..))" id ="perform" />
                   <aop:advisor advice-ref ="tx" pointcut-ref="perform" />
             </aop:config>
</beans>
 
ClassesTest.java
public class ClassesTest {
       @Test
       public void testSaveClasses(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            ClassesService classesService = (ClassesService)context.getBean("classesService" );
            classesService.saveClasses();
      }
}
 
执行结果:
uploading.4e448015.gif正在上传…重新上传取消
 
注:看是否成功为某个类的部分方法加上了事务,可以通过断点调试查看这个类的对象是不是已经变为代理类型。
uploading.4e448015.gif正在上传…重新上传取消
 
 
4、Spring aop配置图
uploading.4e448015.gif正在上传…重新上传取消
uploading.4e448015.gif正在上传…重新上传取消

 

08 Hibernate+Spring-JdbcTemplate

1、Demo
注:在配置sessionFactory的时候,由于sessionFactory中没有设置datasource的方法,所以Spring提供了一个类,这个类即能满足hibernate中sessionFactory的功能,又能满足spring中ioc和di的特征。这个类就是LocalSessionFactoryBean,它所继承的abstractSessionFactoryBean中提供了设置dataSource的方法。
 
Classes.java
public class Classes implements Serializable {
       private Long cid ;
       private String cname ;
       private String description ;
      
       public Long getCid() {
             return cid ;
      }
       public void setCid(Long cid) {
             this.cid = cid;
      }
       public String getCname() {
             return cname ;
      }
       public void setCname(String cname) {
             this.cname = cname;
      }
       public String getDescription() {
             return description ;
      }
       public void setDescription(String description) {
             this.description = description;
      }
}
 
Classes.hbm.xml 
<hibernate-mapping package ="cn.itheima.domain" >
       <class name ="Classes" table="classes" >
             <id name ="cid" column="cid" type="java.lang.Long" length="5" >
                   <generator class ="increment" />
             </id>
             <property name ="cname" column="cname" type="java.lang.String" />
             <property name ="description" column="description" type="java.lang.String" />
       </class>
</hibernate-mapping>
 
ClassesDao.java
public interface ClassesDao {
       public void saveClasses(Classes classes);
}
 
ClassesDaoImpl.java
public class ClassesDaoImpl extends HibernateDaoSupport implements ClassesDao{
 
       public void saveClasses(Classes classes) {
             this.getHibernateTemplate().save(classes);
      }
      
}
 
ClassService.java
public interface ClassesService {
       public void saveClasses(Classes classes );
}
 
ClassServiceImpl.java
public class ClassesServiceImpl implements ClassesService {
 
       private ClassesDao classesDao ;
      
       public ClassesDao getClassesDao() {
             return classesDao ;
      }
 
       public void setClassesDao(ClassesDao classesDao) {
             this.classesDao = classesDao;
      }
 
       public void saveClasses(Classes classes ) {
             classesDao.saveClasses(classes);
      }
 
}
 
hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd" >
 
<hibernate-configuration>
<session-factory>
       <property name ="hibernate.dialect" >
            org.hibernate.dialect.MySQLDialect
       </property>
 
       <property name ="hibernate.connection.driver_class" >
            com.mysql.jdbc.Driver
       </property>
       <property name ="hibernate.connection.username" >root</ property>
       <property name ="hibernate.connection.password" >sorry</ property>
       <property name ="hibernate.connection.url" >
            jdbc:mysql://localhost:3306/myhibernate
       </property>
 
       <property name ="hbm2ddl.auto" >update</ property>
       <property name ="hibernate.dialect" >
            org.hibernate.dialect.MySQLDialect
       </property>
       <property name ="show_sql" >true</ property>
       <property name ="current_session_context_class" >thread</ property>
       <mapping resource ="cn/itheima/domain/Classes.hbm.xml" />
 
</session-factory>
</hibernate-configuration>
 
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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
      
             <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
                <property name ="locations" >
                    <value> classpath:jdbc.properties</value >
                </property>
             </bean>
 
             <bean id ="dataSource" destroy-method="close"
                  class="org.apache.commons.dbcp.BasicDataSource" >
                <property name ="driverClassName" value="${jdbc.driverClassName}" />
                <property name ="url" value="${jdbc.url}" />
                <property name ="username" value="${jdbc.username}" />
                <property name ="password" value="${jdbc.password}" />
             </bean>
            
             <bean name ="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
                   <!-- 第一种配置sessionFactory的方式,这种方式必须自己配置数据源 -->
                   <!--
                  <property name="dataSource" ref="dataSource"></property>
                  <property name="mappingResources">
                        <list>
                              <value>cn/itheima/domain/Classes.hbm.xml</value>
                        </list>
                  </property>
                   -->
                   <!-- 第二种配置sessionFactory的方式,这种方式不必自己配置数据源,也就是上面的配置数据源的配置代码可以都不用写 -->
                   <property name ="configLocation" >
                         <!--
                              这里还可以配置configLocations,也就是配置多个hibernate.cfg.xml文件,
                              也可以配置mappingLocation以及mappingResources
                         -->
                         <value> classpath:hibernate.cfg.xml</value >
                   </property>
             </bean>
            
             <bean id ="classesDao" class="cn.itheima.jdbc.ClassesDaoImpl" >
                   <!--
                        由于ClassesDao继承了HibernateDaoSupport,HibernateDaoSupport有设置sessionFactory的set方法
                   -->
                <property name ="sessionFactory" >
                   <ref bean ="sessionFactory" />
                </property>
             </bean>
            
             <bean id ="classesService" class="cn.itheima.jdbc.ClassesServiceImpl" >
                <property name ="classesDao" >
                   <ref bean ="classesDao" />
                </property>
             </bean>
            
            
             <bean id ="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" >
                   <property name ="sessionFactory" >
                         <ref bean ="sessionFactory" />
                   </property>
             </bean>
 
             <tx:advice transaction-manager ="transactionManager" id= "tx">
                   <tx:attributes>
                         <tx:method name ="save*" read-only="false" />
                   </tx:attributes>
             </tx:advice>
            
             <aop:config>
                   <aop:pointcut expression ="execution(* cn.itheima.jdbc.ClassesServiceImpl.*(..))" id ="perform" />
                   <aop:advisor advice-ref ="tx" pointcut-ref="perform" />
             </aop:config>
 
</beans>
 
ClassesTest.java
public class ClassesTest {
       @Test
       public void testSaveClasses(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            ClassesService classesService = (ClassesService)context.getBean("classesService" );
            System. out.println(classesService);
      }
}
 
执行结果:
cn.itheima.jdbc.ClassesServiceImpl@c8570c
 
注:如果按照上面的步骤执行了,并且sql语句也已经打印出来了,但是数据库并没有任何的变化,这时候极有可能是因为目标方法并没有加上事务,所以操作回滚了。这时候就可以通过查看目标类的对象是否是代理的方式进行检查。
 
 
2、利用注解的方式实现上面的效果
ClassesDaoImpl.java
@Repository(value="classesDao" )
public class ClassesDaoImpl implements ClassesDao{
      
       @Resource(name="hibernateTemplate" )
       private HibernateTemplate hibernateTemplate ;
      
       public void saveClasses(Classes classes) {
             this.hibernateTemplate .save(classes);
      }
      
}
 
ClassesServiceImpl.java
@Service(value="classesService" )
@Transactional //配置整个类的所有方法都加上事务
public class ClassesServiceImpl implements ClassesService {
 
       private ClassesDao classesDao ;
      
       public ClassesDao getClassesDao() {
             return classesDao ;
      }
 
       public void setClassesDao(ClassesDao classesDao) {
             this.classesDao = classesDao;
      }
 
       public void saveClasses(Classes classes) {
             classesDao.saveClasses(classes);
      }
 
}
 
applicationContext.java
<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
      
             <context:component-scan base-package="cn.itheima.jdbc" ></context:component-scan>
             <!--
                  <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
             -->
             <!--
                  事务的注解解析器
              -->
             <tx:annotation-driven transaction-manager="transactionManager" />
            
             <bean id ="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
                   <property name ="configLocation" >
                         <value> classpath:hibernate.cfg.xml</value >
                   </property>
             </bean>
            
             <bean id ="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" >
                   <property name ="sessionFactory" >
                         <ref bean ="sessionFactory" />
                   </property>
             </bean>
            
             <bean id ="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate" >
                   <property name ="sessionFactory" >
                         <ref bean ="sessionFactory" />
                   </property>
             </bean>
</beans>
 
 
3、为某个类的某个方法加上事务
ClassesServiceImpl.java
@Service(value="classesService" )
public class ClassesServiceImpl implements ClassesService {
 
       private ClassesDao classesDao ;
      
       public ClassesDao getClassesDao() {
             return classesDao ;
      }
 
       public void setClassesDao(ClassesDao classesDao) {
             this.classesDao = classesDao;
      }
      
       @Transactional//为某个类中的某个方法加上事务
       public void saveClasses(Classes classes) {
             classesDao.saveClasses(classes);
      }
 
}
 
 
4、设置加上事务的方法是否可以执行写操作
ClassesTest.java
public class ClassesTest {
       @Test
       public void testSaveClasses(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
            ClassesService classesService = (ClassesService)context.getBean("classesService" );
            Classes classes = new Classes();
            classes.setCname( "aaaa");
            classesService.saveClasses(classes);
      }
}
 
SessionServiceImpl.java
@Service(value="classesService" )
public class ClassesServiceImpl implements ClassesService {
 
       @Resource(name="classesDao" )
       private ClassesDao classesDao ;
      
       @Transactional(readOnly=true)
       public void saveClasses(Classes classes) {
             classesDao.saveClasses(classes);
      }
 
}
 
执行结果:
uploading.4e448015.gif正在上传…重新上传取消
 
注:之所以会有DaoSupport并且由HibernateDaoSupport去继承它,是因为进行crud的操作都是面向接口编程的,程序一旦出错,很有可能是在datasource或者sessionFactory注入的时候出的错。所以DaoSupport中提供了一个checkDaoConfig方法,去确定SessionFactory或者dataSource是否成功注入了。并且不同的实现类给出不同的提示。

 

09 三大框架整合

1、三大框架的整合步骤
<1>准备好环境
jar包和hibernate.cfg.xml。
<2>准备spring的配置文件
引入sessionFactory和测试sessionFactory。
<3>建立dao和service。
<4>在spring的配置文件中把dao和service注入。
<5>测试spring的声明式事务环境是否搭建完成。
<6>建立action。
<7>写struts2的配置文件。
<8>写web.xml。
<9>写页面。
<10>测试。
 
注:在做项目中一定要分包明确,有时候可能需要将配置文件和源码以及jar包按照功能细分,分别放入单独的文件夹中。
 
2、具体步骤
<1>创建好相应的文件夹 ,并且三个框架的相关的jar包 
uploading.4e448015.gif正在上传…重新上传取消
 
<2>配置applicationContext.xml 
uploading.4e448015.gif正在上传…重新上传取消
<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
     
</beans>
 
<3>创建domain对象及其映射文件
uploading.4e448015.gif正在上传…重新上传取消
cn.itheima.ssh.domain.Person.java
public class Person implements Serializable {
       private Long pid ;
       private String pname ;
       private String description ;
      
       public Long getPid() {
             return pid ;
      }
       public void setPid(Long pid) {
             this.pid = pid;
      }
       public String getPname() {
             return pname ;
      }
       public void setPname(String pname) {
             this.pname = pname;
      }
       public String getDescription() {
             return description ;
      }
       public void setDescription(String description) {
             this.description = description;
      }
}
 
cn.itheima.ssh.domain.Person.hbm.xml 
<?xml version ="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
       "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
       "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
 
<hibernate-mapping package ="cn.itheima.ssh.domain" >
       <class name ="Person" table="person" >
             <id name ="pid" column="pid" type="java.lang.Long" length="5" >
                   <generator class ="increment" />
             </id>
             <property name ="pname" column="pname" type="java.lang.String" />
             <property name ="description" column="description" type="java.lang.String" />
       </class>
</hibernate-mapping>
 
<4>配置hibernate.cfg.xml文件并且将映射文件引入其中。
uploading.4e448015.gif正在上传…重新上传取消
<?xml version ="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd" >
 
<hibernate-configuration>
<session-factory>
       <property name ="hibernate.dialect" >
            org.hibernate.dialect.MySQLDialect
       </property>
 
       <property name ="hibernate.connection.driver_class" >
            com.mysql.jdbc.Driver
       </property>
       <property name ="hibernate.connection.username" >root</ property>
       <property name ="hibernate.connection.password" >sorry</ property>
       <property name ="hibernate.connection.url" >
            jdbc:mysql://localhost:3306/myhibernate
       </property>
 
       <property name ="hbm2ddl.auto" >update</ property>
       <mapping resource ="cn/itheima/ssh/domain/Person.hbm.xml" />
 
</session-factory>
</hibernate-configuration>
  
<5>在applicationContext.xml文件中创建配置sessionFactory。 
spring/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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
     
             <bean name ="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
               <property name ="configLocation" >
                     <value> classpath:hibernate/hibernate.cfg.xml</ value >
               </property>
        </bean>
     
</beans>
 
<6>新建一个test目录,写一个BaseSpring专门用于获取Spring应用上下文并且测试能否拿到sessionFactory。
uploading.4e448015.gif正在上传…重新上传取消
 
cn.itheima.ssh.test.BaseSpring.java
public class BaseSpring {
 
       public static ApplicationContext context;
      
       static{
             context = new ClassPathXmlApplicationContext("spring/applicationContext.xml" );
      }
      
}
 
cn.itheima.ssh.test.SessionFactory.java
public class SessionFactoryTest extends BaseSpring {
 
       @Test
       public void testSessionFactory() {
            SessionFactory sessionFactory = (SessionFactory)context .getBean("sessionFactory");
            
      }
}
 
测试结果:
uploading.4e448015.gif正在上传…重新上传取消
<7>写dao和service的接口以及实现类。
cn.itheima.ssh.dao.PersonDao.java
public interface PersonDao {
       public void savePerson(Person person);
}
 
cn.itheima.ssh.dao.impl.PersonDaoImpl.java
public class PersonDaoImpl extends HibernateDaoSupport implements PersonDao {
 
       public void savePerson(Person person) {
             this.getHibernateTemplate().save(person);
      }
 
}
 
cn.itheima.ssh.service.PersonService.java
public interface PersonService {
       public void savePerson (Person person);
}
 
cn.itheima.ssh.serivce.impl.PersonServiceImpl.java
public class PersonServiceImpl implements PersonService {
      
       private PersonDao personDao ;
      
       public PersonDao getPersonDao() {
             return personDao ;
      }
 
       public void setPersonDao(PersonDao personDao) {
             this.personDao = personDao;
      }
 
       public void savePerson(Person person) {
             this.personDao .savePerson(person);
      }
 
}
 
<8>将spring的db、bean配置专门写在两个配置文件中,并且引入到applicationContext.xml文件中
applicationContext-db.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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
     
             <bean name ="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
 
                   <property name ="configLocation" >
                         <value> classpath:hibernate/hibernate.cfg.xml</ value >
                   </property>
             </bean>
           
             <bean id ="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" >
                   <property name ="sessionFactory" >
                         <ref bean ="sessionFactory" />
                   </property>
             </bean>
 
             <tx:advice transaction-manager ="transactionManager" id= "tx">
                   <tx:attributes>
                         <tx:method name ="save*" read-only="false" />
                         <tx:method name ="update*" read-only="false" />
                         <tx:method name ="delete*" read-only="false" />
                         <!-- 表示出了上面情况以外所有的情况 -->
                         <tx:method name ="*" read-only="true" />
                   </tx:attributes>
             </tx:advice>
           
             <aop:config>
                   <aop:pointcut expression ="execution(* cn.itheima.ssh.service.impl.PersonServiceImpl.*(..))" id ="perform" />
                   <aop:advisor advice-ref ="tx" pointcut-ref="perform" />
             </aop:config>
 
</beans>
 
applicationContext-person.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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
     
           <bean id ="personDao" class="cn.itheima.ssh.dao.impl.PersonDaoImpl" >
              <property name ="sessionFactory" >
                 <ref bean ="sessionFactory" />
              </property>
           </bean>
         
           <bean id ="personService" class="cn.itheima.ssh.service.impl.PersonServiceImpl" >
              <property name ="personDao" >
                 <ref bean ="personDao" />
              </property>
           </bean>
           
</beans>
 
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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
     
             <import resource ="applicationContext-db.xml" />
             <import resource ="applicationContext-person.xml" />
</beans>
 
<9>写一个PersonTest,测试PersonService是否变为代理对象执行相关的方法。
cn.itheima.test.PersonTest.java 
public class PersonTest extends BaseSpring {
 
       @Test
       public void testPerson(){
            PersonService personService = (PersonService)context .getBean("personService");
            Person person = new Person();
            person.setPname( "aaa");
             personService.savePerson(person);
      }
}
 
测试结果:
uploading.4e448015.gif正在上传…重新上传取消
 
<10>写一个action,然后进行测试
cn.itheima.ssh.action.PersonAction.java
public class PersonAction extends ActionSupport {
       private PersonService personService ;
 
       public PersonService getPersonService() {
             return personService ;
      }
 
       public void setPersonService(PersonService personService) {
             this.personService = personService;
      }
      
       public String savePerson(){
            Person person = new Person();
            person.setPname( "dddd");
             this.personService .savePerson(person);
             return null ;
      }
}
 
applicationContext-person.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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
     
           <bean id ="personDao" class="cn.itheima.ssh.dao.impl.PersonDaoImpl" >
              <property name ="sessionFactory" >
                 <ref bean ="sessionFactory" />
              </property>
           </bean>
         
           <bean id ="personService" class="cn.itheima.ssh.service.impl.PersonServiceImpl" >
              <property name ="personDao" >
                 <ref bean ="personDao" />
              </property>
           </bean>
          
           <bean id ="personAction" class="cn.itheima.ssh.action.PersonAction" scope="prototype" >
              <property name ="personService" >
                 <ref bean ="personService" />
              </property>
           </bean>
           
</beans>
 
PersonTest.java
public class PersonTest extends BaseSpring {
 
       @Test
       public void testPerson(){
            PersonService personService = (PersonService)context .getBean("personService");
            Person person = new Person();
            person.setPname( "aaa");
            personService.savePerson(person);
      }
      
       @Test
       public void testPersonAction (){
            PersonAction personAction = (PersonAction)context .getBean("personAction");
            personAction.savePerson();
      }
      
}
 
<11>写struts-person.xml并且include进struts.xml文件中,在web.xml文件中进行struts2的filter和ContextLoaderListener的配置。
uploading.4e448015.gif正在上传…重新上传取消
struts-person.xml
<?xml version ="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd" >
 
<struts>
       <package name ="person" namespace="/" extends="struts-default" >
             <!-- 这里的class已经不是类全名了,因为struts的action交给了spring进行管理,所以这里的class必须与spring的bean的名称是一致的 -->
                   <action name ="personAction_*" method="{1}" class="personAction" ></action>
       </package>
</struts>
 
struts.xml
<?xml version ="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd" >
 
<struts>
       <constant name ="struts.devMode" value="true" />
       <constant name ="struts.ui.theme" value="simple" />
       <include file ="struts/struts-person.xml" ></include>
</struts>
 
web.xml 
<?xml version ="1.0" encoding="UTF-8" ?>
<web-app version ="2.4"
       xmlns="http://java.sun.com/xml/ns/j2ee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
      http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" >
 
       <listener>
             < listener-class>org.springframework.web.context.ContextLoaderListener </listener-class>
       </listener>
       <context-param>
             <param-name> contextConfigLocation</param-name >
             < param-value>classpath:spring/applicationContext.xml </param-value>
       </context-param>
      
         <filter>
              <filter-name> struts2</filter-name >
              <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class>
          </filter>
      
          <filter-mapping>
              <filter-name> struts2</filter-name >
              <url-pattern> /*</ url-pattern>
          </filter-mapping>
 
        <welcome-file-list>
          <welcome-file> index.jsp</welcome-file >
        </welcome-file-list>
</web-app>
 
测试结果:
uploading.4e448015.gif正在上传…重新上传取消
uploading.4e448015.gif正在上传…重新上传取消
注:
<1>ContextLoaderListener继承了ServletContextListener,在容器启动的时候,就可以做一些操作。
uploading.4e448015.gif正在上传…重新上传取消
<2>Struts-plugin.xml
uploading.4e448015.gif正在上传…重新上传取消
这个配置的目的在于将bean创建的功能交给spring。
uploading.4e448015.gif正在上传…重新上传取消
 
总结:
1、Spring与hibernate整合
<1>Spring 的声明式事务处理
<2>Spring以模板的方式把数据库的操作进行了封装。
2、Spring与tomcat整合
<1>当tomcat容器启动的时候,spring容器启动了。
<2>当spring容器启动的时候,只要不是scope为prototype,lazy-init="true",所有的类都实例化了。
3、Spring与struts2的结合点
Spring帮助struts2生成了action。
4、应用spring的IOC和DI做了action与service,service与dao之间的松耦合。
 

 

10 OpenSessionInView

1、如果在dao层执行如下的代码
this.getHibernateTemplate().load(Person.class,id);
则产生的对象是代理对象。
 
2、在页面中执行${requestScope.person.pname},这个时候,会向数据库要数据,而session已经关闭了。
 
3、解决方案: 
在web.xml中添加:
<filter >
    <filter-name >OpenSessionInViewFilter</ filter-name>
    <filter-class> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter </filter-class>
</filter>
 
<filter-mapping>
    <filter-name >OpenSessionInViewFilter</ filter-name>
    <url-pattern >/*.action</ url-pattern>
</filter-mapping>
 
说明:
<1>当tomcat容器启动的时候,spring容器已经启动了,这个时候sessionFactory已经生成了。
<2>OpenSessionInViewFilter过滤器产生了session,当执行finally的时候把session关闭了。(当整个页面的数据加载出来的时候执行finally)。
<3>OpenSessionInViewFilter该过滤器会延长session的关闭时间,也就意味着一级缓存中的数据会被长时间停留在内存中,所以可以在程序中适当的清空一级缓存。
 
注:
<1>如果没有openSessionInView,那么如果测试的方法没有事务环境,当this.getHibernateTemplate().load/get/...方法调用完毕以后,session关闭了。同一个方法后面的代码如果涉及到session,那么就会报异常。
<2>如果测试的方法有事务环境,则调用完成该方法以后,事务就关闭了。例如,一个加了事务环境的方法里面只使用了load方法,那么如果在后面调用这个load进来的对象就会报错。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值