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" );
}
}
<?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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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;
}
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
* 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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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 ;
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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.gif)
Person.java
@Autowired
@Qualifier(value="studen" )
private Student student ;
执行结果:
![uploading.4e448015.gif](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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容器的时候,就去解析配置文件,找到
* 就会去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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.gif)
![uploading.4e448015.gif](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.gif)
![uploading.4e448015.gif](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.gif)
![uploading.4e448015.gif](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.gif)
注:事务的传播属性
Required:业务方法需要在一个事务中运行,如果方法运行时,已经处在一个事务中,那么加入到该事务,否则为自己创建一个新的事务。
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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.gif)
注:看是否成功为某个类的部分方法加上了事务,可以通过断点调试查看这个类的对象是不是已经变为代理类型。
![uploading.4e448015.gif](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.gif)
4、Spring aop配置图
![uploading.4e448015.gif](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.gif)
![uploading.4e448015.gif](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.gif)
<2>配置applicationContext.xml
![uploading.4e448015.gif](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.gif)
![uploading.4e448015.gif](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.gif)
注:
<1>ContextLoaderListener继承了ServletContextListener,在容器启动的时候,就可以做一些操作。
![uploading.4e448015.gif](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.gif)
<2>Struts-plugin.xml
![uploading.4e448015.gif](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.gif)
这个配置的目的在于将bean创建的功能交给spring。
![uploading.4e448015.gif](https://i-blog.csdnimg.cn/blog_migrate/8d6f93dd9c49cf646dd2deaf19080974.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进来的对象就会报错。