SSH之Spring

Spring的优点
低侵入式设计,代码的污染极低
独立于各种应用服务器
Spring的IoC容器降低了业务对象替换的复杂性,提高了组件之间的解耦
Spring的AOP支持允许将一些通用任务如安全、事务、日志等进行集中式处理,从而提供了更好的复用
Spring的ORM和DAO提供了第三方持久层框架的良好整合,简化了底层的数据库访问
Spring的高开放性,并不强制应用完全依赖于Spring,开发者可以自由选用Spring框架的部分或全部
依赖Jar包
Spring-framework-4.0.4.Final
common-logging
对Spring而言,一切对象都是Bean
Spring框架的核心功能
Spring容器作为超级大工厂,负责创建、管理所有的Java对象(Bean)
Spring容器管理容器中Bean之间的依赖关系,Spring使用一种“依赖注入”的方式来管理Bean之间的依赖关系
依赖注入一般有两种
-》设值注入:IoC容器使用成员变量的setter方法来注入被以来对象
Person Axe
-Chinese -StoneAxe
beans.xml
<beans >
<!-- 配置Chinese实例 -->
<bean id="chinese" class="com.spring.dao.Chinese">
<property name="axe" ref="stomeAxe"/>
</bean>
<bean id="stomeAxe" class="com.spring.dao.StomeAxe"/>
</beans>

ApplicationContext context = new ClassPathXmlApplicationContext(
"beans.xml");
Person person = context.getBean("chinese", Person.class);
person.useAxe();
Spring IoC容器的要点
->应用程序的各组件面向接口编程,面向接口棉城可以将组件之间的耦合关系提升到接口层次,从而有利于项目后期抽到扩展
->应用程序的各组件不再由程序自助创建,而是由Spring容器来负责产生并初始化
->Spring采用配置文件或者注解来管理Bean的实现类、依赖关系,Spring容器啧根据配置文件或注解,利用反射来创建实例
-》构造注入:IoC容器使用构造器来注入被以来对象
Person Axe
-Chinese -StoneAxe
public Chinese(Axe axe) {

// TODO Auto-generated constructor stub
this.axe = axe;
}

<bean id="chinese" class="com.spring.dao.Chinese">
<constructor-arg ref="stomeAxe"></constructor-arg>
</bean>
<bean id="stomeAxe" class="com.spring.dao.StomeAxe"/>
</beans>
Spring框架的本质:通过XML配置来驱动Java代码,这样就可以把原本由Java代码管理的耦合关系,提取到XML配置文件中管理,这就实现了系统中各组件的解耦,有利于后期的升级和维护
容器中Bean的作用域
->singleton(默认):单例模式,在整个SpringIoC容器中,singleton作用域的Bean将只生成一个实例
->prototype:每次通过容器的getBean()方法获取prototype作用域的Bean时,都将产生一个新的Bean实例

设置普通属性值
<bean >
<property name="firstField" value="1"/>
<property name="secondField valye="2"/>
</bean>
配置合作者
<bean>
<property name="axe" ref="Axe"/>
</bean>
使用自动装配注入合作者Bean
->byName :根据setter方法名进行自动装配,Spring容器查找容器中的全部Bean,找出其id与setter方法名去掉set前缀,并小写首字母后同名的Bean来完成注入,如果没有找到匹配的Bean实例,Spring不进行任何注入
->byType:根据setter方法的形参类型来自动装配。Spring容器查找容器中的全部Bean,如果正好有一个Bean类型与setter方法的形参类型匹配,就自动注入这个Bean;如果找到多个这样的Bean,就抛出一个异常,如果没有找到这样的Bean,什么都不会发生
Spring中Bean满足的原则
->尽量为每个Bean实现类提供无参数的构造器
->接受构造注入的Bean,则应提供对应的、带参数的构造函数
->接受设值注入的Bean,则应提供邸的setter方法,并不要求提供对应的getter方法
JavaBean和Spring中的Bean存在的区别
1.用处不同:JavaBean更多是作为值对象传递参数,Spring的Bean用处几乎无所不包,任何应用组件都被chengweiBean
2.写法不同:javaBean作为值对象,要求每个属性都提供getter和setter方法,蛋Spring中的Bean只需为接受设值注入的属性提供setter方法即可
3.生命周期不同:JavaBean作为值对象传递,不接受任何容器管理期生命周期,Spring中的Bean由Spring管理其生命周期行为
Spring3.0提供的Java配置管理
@Configuration
public class AppConfig {
@Value("孙悟空")
String personName;
@Bean(name = "chinese")
public Person person() {
Chinese p = new Chinese();
p.setAxe(StomeAxe());
return p;
}
@Bean(name = "stomeAxe")
public Axe StomeAxe() {
// TODO Auto-generated method stub
return new StomeAxe();
}
}
Java配置类的Annotation
-》@configuration:用于修饰一个Java配置类
-》@Bean:用于修饰一个方法,将该方法的返回值定义成容器中的一个Bean
-》@Value:用于修饰一个Field,用于为该Field配置一个值,相当于配置一个变量
-》@Import:修饰一个Java类,用于向当前的Java配置类中导入其他的Java配置类
-》@Scope:用于修饰一个方法,指定该方法对应的Bean的生命域
-》@Lazy:用于修饰一个方法,指定该方法对应的Bean是否需要延迟初始化
-》@DependsOn:用于修饰一个方法,指定在初始化该方法对应的Bean之前初始化指定的Bean
创建Bean的三种方式
1、调用构造器创建Bean
2、调用静态工厂方法创建Bean
<bean.../>元素需要指定如下的属性
1、class:该属性的值为静态工厂类的类名
2、factory-method:该属性指定静态工厂方法来生产Bean实例
使用静态工厂方法创建实例必须提供工厂类,工厂类包含产生实例的静态工厂方法。通过静态工厂方法创建实例时需要对配置文件进行如下改变
1、class属性的值不在是Bean实例的实现类,而是生成Bean实例的静态工厂类
2、使用factory-method属性指定创建Bean实例的静态工厂方法
3、如果静态工厂发发需要参数,啧使用<constructor-arg.../>元素指定静态工厂方法的参数
3、调用实例工厂方法创建Bean
<bean.../>元素需要指定如下两个属性
1、factory-bean:该属性的值为工厂的Bean的id
2、factory-method:该属性指定实力工厂的工厂方法
抽象Bean
<bean...abstract="true"/>
通过为一个<bean.../>元素指定parent属性
--抽象Bean不能被实例化,Spring容器不会实例化抽象Bean,抽象Bean的作用在于被继承
容器中的工厂Bean
必须实现FactoryBean接口
Factory接口提供三个方法
1、T getObject():实现该方法负责返回该工厂Bean生成的Java实例
2、Class <?> getObjectType():实现该方法返回该工厂Bean生成的Java实例的实现类
3、boolean isSingleton():实现该方法表示该工程的Bean生成的Java实例是否为单例模式
容器中Bean的生命周期
->注入依赖关系之后
1、使用init-method属性。代码污染小,不需要将代码与Spring的接口耦合在一起
<bean init-method="init"/>
2、实现InitalizingBean接口
->即将销毁Bean之前
1、使用destroy-method属性。代码污染小,不需要将代码与Spring的接口耦合在一起
<bean destroy-method="close"/>
2、实现DisposableBean接口
Spring框架的本质
开发者在Spring配置文件中使用XML元素进行配置,实际驱动Spring执行相应的代码
-》使用<bean.../>元素,实际驱动Spring执行无参或有参的构造器,或者调用工厂方法创建Bean
-》使用<property.../>元素,实际驱动Spring执行一次setter方法
Spring框架的功能在于可以让开放着无须书写Java代码就可以进行Java编程,当开发者XML采用合适语法进行配置之后,Spring就可以通过反射在底层执行任意的Java代码
until的使用
->constant
指定类的静态Field的值,是FieldRetrievingFactoryBean的简化配置
->property-path
获取指定对象的getter方法的返回值,是PropertyPathFactoryBean的简化配置
->list
定义一个List Bean,支持<value.../><ref.../><bean.../>来定义List集合元素
id:指定定义一个名为id的List Bean实例
list-class:指定Spring使用哪个List实现类来创建Bean 实例,默认使用ArrayList作为实现类
scope:指定该List Bean实例的作用域
->set
定义一个Set Bean,支持<value.../>、<ref.../>、<bean.../>等子元素来定义Set集合元素
id:指定定义一个名为id的Set Bean实例
set-class:指定Spring使用哪个Set实现类来创建Bean实例。默认使用HashSet作为实现类
scope:指定该Set Bean实例的作用域
->map
定义一个Map Bean,支持使用<entry.../>来定义Map的key-value对
id:指定一个名为id的Map Bean实例
map-class:指定Spring使用哪个Map实现类创建Bean实例,默认使用HashMap作为实现类
scope:指定该Mao Bean实例的作用域
->properties
用于加载一份资源文件,并根据加载的资源文件创建一个Properties Bean实例。
id:指定定义一个名为id的Properties Bean实例
location:指定资源文件的位置
scope:指定该Properties Bean实例的作用域
后处理器
Bean后处理器
实现BeanPostProcessor接口
->Object postProcessBeforeInitialization(Object bean,String name)throws BeansExecption
->Object postProcessAfterInitialization(Object bean,String name)throws BeansExecption
(第一个参数是系统即将进行后处理的Bean实例,第二个参数是该Bean的配置id)
<bean id="stomeAxe" class="com.spring.dao.StomeAxe"/>
<bean id ="chinese" class="com.spring.chapter8_1.Chinese"
init-method="init" p:axe-ref="stomeAxe" p:name="依赖注入的值" />
<!-- 配置Bean后吃利器,可以无需指定id属性 -->
<bean class="com.spring.chapter8_1.MyBeanPostProcessor"/>

public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String name)
throws BeansException {
System.out.println("Bean后处理器在初始化之前对" + name + "进行处理");
// TODO Auto-generated method stub
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String name)
throws BeansException {
// TODO Auto-generated method stub
System.out.println("Bean后处理器在初始化之hou对" + name + "进行处理");
if (bean instanceof Chinese) {
Chinese chinese = (Chinese) bean;
chinese.setName("杰爸爸");
}
return bean;
}
public class Chinese implements Person, InitializingBean {}

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
Person p = (Person) ctx.getBean("chinese");
p.useAxe();
Bean后处理器两个方法的回调时机
如果使用BeanFactory作为Spring容器,必须手动注册Bean后处理器,程序必须获取Bean后处理器实例,然后手动注册。主程序为
// 搜索类加载路径下的beans.xml文件穿件Resouce对象
Resource isr = new ClassPathResource("beans.xml");
// 创建默认的BeanFactory容器
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 让默认的BeanFactory容器加载对应的 XML配置文件
new XmlBeanDefinitionReader(beanFactory).loadBeanDefinitions(isr);
// 获取容器中的Bean后处理器
BeanPostProcessor bp = (BeanPostProcessor) beanFactory.getBean("bp");
// 注册Bean后处理器
beanFactory.addBeanPostProcessor(bp);
Person p = (Person) beanFactory.getBean("chinese");
Spring提供的两个常用的后处理器
1、BeanNameAutoProxyCreator:根据实例的name属性,创建Bean实例的代理
2、DefaultAdvistorAutoProxyCreator:根据提供的Advisor,对容器中所有的Bean实例创建代理
容器后处理器
实现BeanFactoryPostProcessor接口
->postProcessBeanFactory(ConfigurableLostableBeanFactory beanFactory)
Spring提供的常用的容器后处理器
1、PropertyPlaceholderConfigurer:属性占位符配置器
2、PropertyPlaceholderConfigurer:重写占位符配置器
3、CustomAutowireConfigurer:自定义自动装配的配置器
4、CustomScopeConfigurer:自定义作用域的配置器
Spring的“零配置”支持
1.搜索Bean类
->@Component:标注一个普通的Spring Bean类
->@Controller:标注一个控制器组件类
->@Service:标注一个业务逻辑组件类
->@Respository:标注一个DAO组件类
beans.xml
<beans xmlns:context="http://www.springframework.org/schema/context"
<!--自动扫面指定包及其子包下的所有Bean类-->
<context: component-scan base-package="****"/>
2.指定Bean的作用域
@Scope("prototype")
3.使用@Resource配置依赖
使用@Resource与<property.../>元素的ref属性有相同的效果
4.使用@PostConstruct和@PreDestroy定制生命周期
@PostConstruct
init()// 表示Spring在该Bean的依赖关系注入完成之后回调该方法
@PreDestory
close()// 表示Spring在销毁该Bean之前回调该方法
资源访问
Resource实现类
UrlResource:访问网络资源的实现类
ClassPathResource:访问类加载路径里资源的实现类
FileSystemResource:访问文件系统里资源的实现类
ServletContextResource:访问相对于ServletContext路径下的资源的实现类
InputStreamResource:访问输入资源的实现类
ByteArrayResouce:访问字节数组资源的实现类
Spring的AOP
AOP分为两类
-》静态AOP:AOP框架在编译阶段对程序进行修改,即实现对目标类的增强,生成静态的AOP代理类(生成的*.class文件已经被改掉,需要使用特定的编译器).以AspectJ为代表
-》动态AOP实现:AOP框架在运行阶段动态生成AOP代理(在内存中以JDK动态代理或cglib动态生成AOP代理类),实现对目标对象的增强,以Spring AOP为代表
AOP基本概念
面向切面编程
-》切面(Aspect):切面用于组织多个Advice,Advice放在切面中定义
-》连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的跑出。在Spring AOP中,连接点总数方法的调用
-》增强处理(Advice):AOP框架在特定的切入点执行的增强处理,处理有"around"、"before"和"after"类型
=》切入点(PointCut):可以插入增强处理的连接点。当某个连接点满足指定要求时,该连接点奖杯添加增强处理,该连接点也就变成了切入点
Spring两种方式定义切入点和增强处理
1、基于注解的“零配置”方式没使用@Aspect、@Pointcut等注解来标注切入点和增强处理
依赖jar包
aspectjweaver.jar
aspectjrt.jar
aopalliance-1.0.jar
Before增强处理
//定义切面
@Aspect
public class AuthAspect {p[]
// 匹配包下所有类
// 所有方法的执行作为切入点
@Before("execution(* com.spring.aop.*.*(..))")
public void authority() {
System.out.println("模拟执行");
}
// 对authority()方法使用了@Before标注,将该方法转换成了一个Before增强处理,直接指定了切入点的表达式,指定匹配包下所有类的所有方法的执行作为切入点
}
@Component
public class HelloImpl implements Hello {

public void foo() {
// TODO Auto-generated method stub
System.out.println("执行Hello组件的foo方法");
}

public void addUser(String name, String pass) {
System.out.println("执行Hello组件的addUser方法" + name);
}
<!-- 启动@AspectJ支持 -->
<aop:aspectj-autoproxy/>
<!-- 指定自动搜索Bean组件、自动搜索切面类 -->
<context:component-scan base-package="com.spring.aop">
<context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/>
</context:component-scan>
AfterReturing增强处理:在目标方法正常完成后被织入
AfterThrowing增强处理:用于处理程序中未处理的异常
After增强处理:目标方法结束(成功完成和遇到异常终止)都会被织入‘
Around增强处理:近似等于Before和AfterReturning增强处理的综合,Around增强处理皆可以在执行目标方法之前织入增强动作,也可以在执行目标方法之后织入增强动作
Around可以决定目标方法在设么时候执行,如何执行,甚至可以完全阻止目标方法的执行
如果需要目标方法执行之前去和之后共享某种状态数据,就使用后Around增强处理,又欲其死需要改变目标方法的返回值,只能使用Around增强处理
@Aspect
public class TxAspect {
Object rvt;

@Around("execution(* com.spring.aop.*.*(..))")
public Object processTx(ProceedingJoinPoint jPoint) {
System.out.println("执行目标方法之前,模拟开始事务");
// 获取目标方法院士的调用参数
Object[] args = jPoint.getArgs();
if (args != null && args.length > 1) {
// 修改目标方法调用参数的第一个参数
args[0] = "[增加的前缀]" + args[0];
}
// 以改变后的参数去执行目标方法,并保存目标方法执行后的返回值
try {
// 以改变后的参数去执行目标方法,并保存目标方法执行后的返回值
rvt = jPoint.proceed(args);
System.out.println("执行目标方法之后,模拟结束事务");
if (rvt != null && rvt instanceof Integer) {
rvt = (Integer) rvt * (Integer) rvt;
}
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rvt;
}
}
运行结果
执行目标方法之前,模拟开始事务
执行Hello组件的addUser方法[增加的前缀]小米
执行目标方法之后,模拟 结束事务
执行目标方法之前,模拟开始事务
执行Hello组件的foo方法
执行目标方法之后,模拟 结束事务
访问目标方法的参数
1、Object[] getArgs():返回执行目标方法时的参数
2、Signature getSignature():返回被增强的方法的相关信息
3、Object getTarget():返回被织入增强处理的目标对象
4、Object getThis():返回AOP框架为目标对象生成的代理对象
当不同切面里的两个增强处理需要在同一个连接点被织入时,Spring AOP将以随机的顺序来织入这两个增强处理。Spring提供了两种指定不同切面类里增强处理的优先级
1、然后切面类实现org.springframework.core.Ordered接口,实现该接口只需实现一个int getOrder()方法,该方法的返回值越小,优先级越高
2、直接使用@Order注解来修饰一个切面类,使用@Order注解时可制定一个int型的value属性,该属性值越小,优先级越高
定义切入点
切入点
->一个切入点表达式
->一个包含名字和任意参数的方法签名
@Aspect
public class MyArh{
@Pointcut("execution(* com.spring.aop.*.*(..))")
public void myPointcut(){}
}
@AfterReturning(returning="rvt",pointcut="MyArh.myPointcut()")
Spring AOP支持的切入点指示符
->execution:execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)
modifiers-pattern:指定方法的修饰符,支持通配符,可省略
ret-type-pattern :指定方法的返回值类型,支持通配符,可以使用 * 通配符来匹配所有的返回值类型
declaring-type-pattern:指定方法所属的类,支持通配符,该部分可省略
name-pattern:指定陪陪指定的方法名,支持通配符,可以使用*来匹配所有的方法
param-pattern:在孤独部分方法生命中的形参列表,支持两个通配符(“*”和“..“),"*"代表一个任意类型的参数,”..“代表零个或多个任意类型的参数
throws-pattern:指定方法声明抛出的异常,支持通配符,可省略
->within:用于限定匹配特定类型的连接点,,当使用Spring AOP的时候,只能匹配方法执行的连接点
->this:用于限定AOP代理必须指定类型的实例,匹配该对象的所有连接点,当使用Spring AOP的时候,只能匹配方法执行的连接点
->target:用于限定目标对象必须是指定类型的实例,匹配该对象的所有连接点,当使用Spring AOP的时候,只能匹配方法执行的连接点
->args:用于对连接点的参数类型进行限制,要求参数类型是指定类型的实例,当使用Spring AOP时,只能匹配方法执行的连接点
->bean:用于限定只匹配指定Bean实例内的连接点,实际上只能使用方法执行作为连接点。定义Bean表达式时需要传入Bean的id或name,表示职匹配该Bean实例内的连接点,支持使用“*”通配符
2、基于XML配置文件的管理方式:使用Spring配置文件来定义切入点和增强处理
1.配置切面
<aop:aspect.../>
id:定义该切面的标志名
ref:用于将ref属性所引用的普通Bean转换为切面Bean
order:指定切面Bean的优先级,order属性值越小,优先级越高
2.配置增强处理
<aop:before.../>配置Before增强处理
<aop:after.../>配置After增强处理
<aop:after-returning.../>配置AfterReturning增强处理
<aop:after-throwing.../>配置AfterThrowing增强处理
<aop:around.../>配置Around增强处理
可指定一下属性
->pointcut:指定一个切入表达式
->pointcut-ref:指定一个已经存在的切入点名称
->method:指定方法名,指定将切面Bean的该方法转化为增强处理
public class FourAdviceTest {
public Object processTx(ProceedingJoinPoint jPoint) throws Throwable {
System.out.println("Around增强:执行目标方法之前,模拟开始事务");
Object[] args = jPoint.getArgs();
if (args != null && args.length > 0) {
args[0] = "[增加的前缀]" + args[0];
}
Object rvtObject = jPoint.proceed(args);
System.out.println("Around:执行方法之后,模拟结束事务");
if (rvtObject != null && rvtObject instanceof Integer) {
rvtObject = (Integer) rvtObject * (Integer) rvtObject;
}
return rvtObject;
}
}
<aop:config>
<aop:aspect id="fourAdviceAspect" ref="fourAdviceBean">
<!-- 定义Around增强 -->
<aop:around pointcut="execution(* com.spring.aop.*.*(..))" method="processTx" />
</aop:aspect>
</aop:config>
<bean id="fourAdviceBean" class="com.spring.aop.FourAdviceTest"></bean>
<bean id="hello" class="com.spring.aop.HelloImpl"/>
Spring缓存机制
EnCache缓存实现的配置
ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<diskStore path="java.io.tmpdir"/>
<!-- 配置默认的缓存区 -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxElementsOnDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolcy="LRU"/>
<cache name="users"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"/>
</ehcache>

<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-3.1.xsd">
<!--开启cache扫描-->
<cache:annotation-driven cache-manager="cacheManager"/>
<context:component-scan base-package="com.spring.cache"/>
<aop:config proxy-target-class="true"/>
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:configLocation="classpath:ehcache.xml"
p:shared="false"/>
<!-- 配置基于EhCache的缓存管理期,并将EhCache的CacheManager注入该缓存管理期Bean -->
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"
p:cacheManager-ref="ehCacheManager"/>
</beans>

@Service("userService")
@Cacheable(value = "users", key = "#name")
public class UserService {

public User getUserByNameAndAge(String name, int age) {
System.out.println("---执行findUserByNameAndAge()查询方法");
return new User(name, age);
}
}
public class CacheTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"beans2.xml");
UserService us = ctx.getBean("userService", UserService.class);
// 第一次调用us对象的方法时会执行该方法并缓存方法的结果
User user1 = us.getUserByNameAndAge("小明", 110);
// 第二次调用us的对象的方法时直接利用缓存的数据,并不真正执行该方法
User user2 = us.getUserByNameAndAge("小明", 110);
System.out.println(user1 == user2);
}
}
运行结果:
---执行findUserByNameAndAge()查询方法
true
使用@Cacheable可指定如下属性
->value:必需属性,该属性可指定多个缓存区的名字,用于指定将方法返回值放入指定的缓存区内
->key:通过SpEL表达式显式指定缓存的Key
->condition:指定一个返回的boolean值的SpEL表达式,只有当该表达式返回true时,Spring才会缓存方法返回值
->unless:指定一个返回boolean值的SpEL表达式,当表达式返回true时,Spring就不缓存方法的返回值
@CacheEvict清除缓存
->value:必需属性,指定该方法用于清除哪个缓存区的数据
->allEntries:指定是否清空整个缓存区
->beforeInvocation:指定是否在执行方法之前清除缓存,默认是在方法成功完成之后才清除缓存
->condition:指定给一个SpEL表达式,只有当该表达式为true时菜清除缓存
->key:通过SpEL表达式显式指定缓存的key

Spring的事务
public class NewDao {
private DataSource dSource;

public void setdSource(DataSource dSource) {
this.dSource = dSource;
}

public void insert(String title, String content) {
JdbcTemplate jTemplate = new JdbcTemplate(dSource);
jTemplate.update("insert into news_inf" + " value(null,?,?,null,null)",
title, content);
jTemplate.update("insert into news_inf" + " value(null,?,?)", title,
content);
}
}
<!-- 定义数据源Bean,使用C3P0数据源实现,并注入数据源的必要信息 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
p:driverClass="com.mysql.jdbc.Driver"
p:jdbcUrl="jdbc:mysql://localhost/hibernate"
p:user="root"
p:password="root"
p:maxPoolSize="40"
p:minPoolSize="2"
p:initialPoolSize="2"
p:maxIdleTime="30"
/>
<!-- 配置JDBC数据源的局部事务管理期,使用 DataSourceTransactionManager类-->
<!--要注入DataSource的使用 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"/>
<!-- 配置一个业务逻辑Bean -->
<bean id="newDao" class="com.spring.shiwu.NewDao"
p:dSource-ref="dataSource"/>
<!-- 配置事务增强处理Bean,指定事务管理器 -->
<tx:advice id="txAdvice"
transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*" isolation="DEFAULT" propagation="REQUIRED" timeout="5"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(* com.spring.shiwu.*.*(..))" id="myPointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"/>
</aop:config>

public class Test {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"beans_shiwu.xml");
NewDao newDao = ctx.getBean("newDao", NewDao.class);
newDao.insert("杰哥", "真厉害");
}
}
运行结果:
错误: PreparedStatementCallback; bad SQL grammar [insert into news_inf value(null,?,?)]; nested exception is java.sql.SQLException: Column count doesn't match value count at row 1
insert()方法所执行的两条SQL语句全部回滚
使用@Transactional注解
需要在xml中加入
<tx:annotation-driven transaction-manager="transactionManager"/>

采用工厂模式的顺序图
启动Spring容器
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app xmlns="http://xmlns.jcp.org/xml/nx/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/nx/javaee
http://xmlnx.jcp.org/xml/nx/javaee/web-app_3_1.xsd" version="3.1">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 指定多个配置文件 -->
<context-param>
<!-- 参数名为contextConfigLocation -->
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<!--让Struts 2的核心Filter拦截所有请求-->
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
控制器如何获得业务逻辑组件
1.服务器定位器模式(经典的JavaEE)
2.工厂模式(对于轻量级的JavaEE应用)

控制器访问Spring容器中的业务逻辑组件的策略
1.Spring容器管理控制器Action,并利用依赖注入为控制器注入业务逻辑组件

LoginAction.java
public class LoginAction extends ActionSupport {
private String name;
private String password;
private MyService myservice;

public void setMyservice(MyService myservice) {
this.myservice = myservice;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
if (myservice.validLogin(getName(), getPassword()) > 0) {
addActionMessage("哈哈哈,整合成功");
return SUCCESS;
}

return ERROR;
}
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<!-- 配置一系列常量 -->
<constant name="struts.i18n.encoding" value="utf-8"></constant>
<constant name="strurs.devMode" value="true"></constant>
<constant name="struts.enable.DynamicMethodInvocation" value="false"></constant>
<package name="Struts" extends="struts-default">
<!-- 定义处理用户请求的Action,该Action的class属性不是实际处理类,而是Spring容器中的Bean实例的ID -->
<action name="login" class="loginAction">
<result name="error">/content/error.jsp</result>
<result name="success">/content/success.jsp</result>
</action>
<action name="login1" class="com.spring.struts2.Test">
<result name="error">/content/error.jsp</result>
<result name="success">/content/success.jsp</result>
</action>
<!-- 让用户直接访问该应用时列出所有的视图页面 -->
<action name="*">
<result>/content/{1}.jsp</result>
</action>
</package>
</struts>
MyService.java
public class MyService {
public int validLogin(String name, String password) {
// TODO Auto-generated method stub
if (name.equals("dad") && password.equals("dad")) {
return 99;
}
return -1;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<!-- 定义一个业务逻辑组件,实现类为MyService -->
<bean id="myService" class="com.spring.struts2.MyService"/>
<bean id="loginAction" class="com.spring.struts2.LoginAction"
scope="prototype" p:myservice-ref="myService"/>
</beans>

2.利用Spring的自动装配
<action name="login" class="com.spring.struts2.LoginAction">
private MyService myservice ;

public void setMyservice(MyService myservice) {
this.myservice = myservice;
}
<bean id= "myservice" class="com.spring.struts2.MyService"/>

Spring整合Hibernate
DAO:所有的数据库访问都通过DAO组建完成,DAO组件封装了数据库的增删改等资源自操作,业务逻辑组件依赖于DAO组件提供的数据库原子操作,完成系统业务逻辑的实现
Java EE应用分为
-》表现层
-》业务逻辑层
-》数据持久层
Java EE应用各组件之间的调用关系
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<!-- 配置一系列常量 -->
 <constant name="struts.i18n.encoding" value="utf-8"></constant>
<constant name="strurs.devMode" value="true"></constant>
<constant name="struts.enable.DynamicMethodInvocation" value="false"></constant>
<package name="Struts" extends="struts-default">
<!-- 定义处理用户请求的Action,该Action的class属性不是实际处理类,而是Spring容器中的Bean实例的ID -->
<action name="addBook" class="com.spring.action.BookAction">
<result name="error">/content/error.jsp</result>
<result name="success">/content/success.jsp</result>
</action>

</package>
</struts>    



web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app xmlns="http://xmlns.jcp.org/xml/nx/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/nx/javaee
http://xmlnx.jcp.org/xml/nx/javaee/web-app_3_1.xsd" version="3.1">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<!--让Struts 2的核心Filter拦截所有请求-->
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>


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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:cache="http://www.springframework.org/schema/cache"  
       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
            http://www.springframework.org/schema/tx 
            http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
            http://www.springframework.org/schema/mvc 
            http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/cache 
            http://www.springframework.org/schema/cache/spring-cache-3.1.xsd"
            >
        <!-- 配置c3p0数据库连接池 -->
            <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"
            p:driverClass="com.mysql.jdbc.Driver"
            p:jdbcUrl="jdbc:mysql://localhost/hibernate"
            p:user="root"
            p:password="root"
            p:maxPoolSize="40"
            p:minPoolSize="2"
            p:initialPoolSize="2"
            p:maxIdleTime="30"
           />  
         <!-- 配置SessionFactory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
    p:dataSource-ref="dataSource">
   <property name="annotatedClasses">
   <list>
   <!-- 列出所有的PO类 -->
   <value>com.spring.action.Book</value>
   </list>
   </property>
   <property name="hibernateProperties">
   <props>
   <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
   <prop key="hibernate.hbm2ddl.auto">update</prop>
   <prop key="hibernate.show_sql">true</prop>
   <prop key="hibernate.format_sql">true</prop>
   <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
   </props>
   </property>
    </bean>
<bean id="bookService" class="com.spring.impl.BookServiceImpl" p:bookDao-ref="bookDao"></bean>
<bean id="bookDao" class="com.spring.impl.BookDaoHibernate" p:sessionFactory-ref="sessionFactory"> </bean>
   
  
	<!-- 配置Hibernate的局部事务管理器,使用HibernateTransactionManager类 -->
	<!-- 该类是PlatformTransactionManager接口针对采用Hibernate的特定实现类 -->
	<!-- 配置HibernateTransactionManager需依赖注入SessionFactory -->
	<bean id="transactionManager" 
		class="org.springframework.orm.hibernate4.HibernateTransactionManager"
		p:sessionFactory-ref="sessionFactory"/>

<!-- 配置事务增强处理Bean,指定事务管理器 -->
<tx:advice id="txAdvice" 
	transaction-manager="transactionManager">
	<!-- 用于配置详细的事务定义 -->
	<tx:attributes>
		<!-- 所有以'get'开头的方法是read-only的 -->
		<tx:method name="get*" read-only="true"/>
		<!-- 其他方法使用默认的事务设置,指定超时时长为5秒 -->
		<tx:method name="*" isolation="DEFAULT"
			propagation="REQUIRED" timeout="5"/>
	</tx:attributes>
</tx:advice>
<!-- AOP配置的元素 -->
<aop:config>
	<!-- 配置一个切入点 -->
	<aop:pointcut id="myPointcut" expression="bean(bookService)"/>
	<!-- 指定在myPointcut切入点应用txAdvice事务增强处理 -->
	<aop:advisor advice-ref="txAdvice" 
		pointcut-ref="myPointcut"/>
</aop:config>
</beans>


login.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>添加图书</title>
</head>
<body>
<h3>添加图书</h3>
<s:form action="addBook">
	<s:textfield name="book.name" label="书名"/>
	<s:textfield name="book.price" label="价格"/>
	<s:textfield name="book.author" label="作者"/>
	<tr align="center">
		<td colspan="2">
		<s:submit value="添加" theme="simple"/>
		<s:reset value="重设" theme="simple"/>
		</td>
	</tr>
</s:form>
</body>
</html>


success.jsp
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>全部图书</title>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
</head>
<body>
<h3>全部图书</h3>
<table width="640" border="1">
	<s:iterator value="book" var="b">
		<tr>
			<td><s:property value="name"/></td>
			<td><s:property value="price"/></td>
			<td><s:property value="author"/></td>
		</tr>
	</s:iterator>
</table>
</body>
</html>


BaseDao.java
public interface BaseDao<T> {
	// 根据ID加载实体
	T get(Class<T> entityClazz, Serializable id);

	// 保存实体
	Serializable save(T entity);

	// 更新实体
	void update(T entity);

	// 删除实体
	void delete(T entity);

	// 根据ID删除实体
	void delete(Class<T> entityClazz, Serializable id);

	// 获取所有实体
	List<T> findAll(Class<T> entityClazz);

	// 获取实体总数
	long findCount(Class<T> entityClazz);
}
BaseDaoHibernate.java
public class BaseDaoHibernate<T> implements BaseDao<T> {
	// DAO组件进行持久化操作底层依赖的SessionFactory组件
	private SessionFactory sessionFactory;

	// 依赖注入SessionFactory所需的setter方法
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public SessionFactory getSessionFactory() {
		return this.sessionFactory;
	}

	// 根据ID加载实体
	@SuppressWarnings("unchecked")
	public T get(Class<T> entityClazz, Serializable id) {
		return (T) getSessionFactory().getCurrentSession().get(entityClazz, id);
	}

	// 保存实体
	public Serializable save(T entity) {
		System.out.println("调用了这个方法");
		return getSessionFactory().getCurrentSession().save(entity);
	}

	// 更新实体
	public void update(T entity) {
		getSessionFactory().getCurrentSession().saveOrUpdate(entity);
	}

	// 删除实体
	public void delete(T entity) {
		getSessionFactory().getCurrentSession().delete(entity);
	}

	// 根据ID删除实体
	public void delete(Class<T> entityClazz, Serializable id) {
		getSessionFactory()
				.getCurrentSession()
				.createQuery(
						"delete " + entityClazz.getSimpleName()
								+ " en where en.id = ?0").setParameter("0", id)
				.executeUpdate();
	}

	// 获取所有实体
	public List<T> findAll(Class<T> entityClazz) {
		return find("select en from " + entityClazz.getSimpleName() + " en");
	}

	// 获取实体总数

	public long findCount(Class<T> entityClazz) {
		List<?> l = find("select count(*) from " + entityClazz.getSimpleName());
		// 返回查询得到的实体总数
		if (l != null && l.size() == 1) {
			return (Long) l.get(0);
		}
		return 0;
	}

	// 根据HQL语句查询实体
	@SuppressWarnings("unchecked")
	protected List<T> find(String hql) {
		return (List<T>) getSessionFactory().getCurrentSession()
				.createQuery(hql).list();
	}

	// 根据带占位符参数HQL语句查询实体
	@SuppressWarnings("unchecked")
	protected List<T> find(String hql, Object... params) {
		// 创建查询
		Query query = getSessionFactory().getCurrentSession().createQuery(hql);
		// 为包含占位符的HQL语句设置参数
		for (int i = 0, len = params.length; i < len; i++) {
			query.setParameter(i + "", params[i]);
		}
		return (List<T>) query.list();
	}

	/**
	 * 使用hql 语句进行分页查询操作
	 * 
	 * @param hql
	 *            需要查询的hql语句
	 * @param pageNo
	 *            查询第pageNo页的记录
	 * @param pageSize
	 *            每页需要显示的记录数
	 * @return 当前页的所有记录
	 */
	@SuppressWarnings("unchecked")
	protected List<T> findByPage(String hql, int pageNo, int pageSize) {
		// 创建查询
		return getSessionFactory().getCurrentSession().createQuery(hql)
				// 执行分页
				.setFirstResult((pageNo - 1) * pageSize)
				.setMaxResults(pageSize).list();
	}

	/**
	 * 使用hql 语句进行分页查询操作
	 * 
	 * @param hql
	 *            需要查询的hql语句
	 * @param params
	 *            如果hql带占位符参数,params用于传入占位符参数
	 * @param pageNo
	 *            查询第pageNo页的记录
	 * @param pageSize
	 *            每页需要显示的记录数
	 * @return 当前页的所有记录
	 */
	@SuppressWarnings("unchecked")
	protected List<T> findByPage(String hql, int pageNo, int pageSize,
			Object... params) {
		// 创建查询
		Query query = getSessionFactory().getCurrentSession().createQuery(hql);
		// 为包含占位符的HQL语句设置参数
		for (int i = 0, len = params.length; i < len; i++) {
			query.setParameter(i + "", params[i]);
		}
		// 执行分页,并返回查询结果
		return query.setFirstResult((pageNo - 1) * pageSize)
				.setMaxResults(pageSize).list();
	}
}


BookService.java
public interface BookService {
	// 添加图书
	int addBook(Book book);

	List<Book> getAllBooks();

	void deleteBook(int id);
}
BookDaoHibernate.java
public class BookDaoHibernate extends BaseDaoHibernate<Book> implements BookDao {

}
BookServiceImpl.java
public class BookServiceImpl implements BookService {
	private BookDao bookDao;

	public void setBookDao(BookDao bookDao) {
		this.bookDao = bookDao;
	}

	@Override
	public int addBook(Book book) {
		return (Integer) bookDao.save(book);
	}

	@Override
	public List<Book> getAllBooks() {
		return bookDao.findAll(Book.class);
	}

	@Override
	public void deleteBook(int id) {
		bookDao.delete(Book.class, id);
	}
}


BookDao.java
public interface BookDao extends BaseDao<Book> {

}
Book.java
@Entity
@Table(name = "bookss_inf")
public class Book {
	@Id
	@Column(name = "book_id")
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	@Column(name = "book_name")
	private String name;
	private double price;
	private String author;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}
}
BookAction.java
public class BookAction extends ActionSupport {
	private BookService bookService;

	// 依赖注入BookService组件必须的setter方法。
	// 该方法的方法名要与BookService的配置id对应
	public void setBookService(BookService bookService) {
		this.bookService = bookService;
	}

	private Book book;
	private List<Book> books;
	private int id;

	public Book getBook() {
		return book;
	}

	public void setBook(Book book) {
		this.book = book;
	}

	public List<Book> getBooks() {
		return books;
	}

	public void setBooks(List<Book> books) {
		this.books = books;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	// 处理添加图书的add()方法
	public String add() {
		// 调用业务逻辑组件的addBook()方法来处理用户请求
		int result = bookService.addBook(book);
		if (result > 0) {
			// addActionMessage("恭喜您,图书添加成功!");
			return SUCCESS;
		}
		// addActionError("图书添加失败,请重新输入!");
		return ERROR;
	}

	public String list() {
		setBooks(bookService.getAllBooks());
		return SUCCESS;
	}

	public String delete() {
		bookService.deleteBook(id);
		return SUCCESS;
	}

	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		return add();
	}
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值