Spring : DEMO
设计模式:
工厂模式 (使用一个专门的类,这个类负责创建系列的对象 ) (Spring容器相当于一个工厂)
优点:对象的依赖者(如Computer)和被依赖者(如Printer)可以彻底分离
值得改进:当我们需要升级被依赖者(Printer),虽然依赖者的代码无需改变,但需要改变工厂的代码 (放到配置文件里管理,如spring)
静态工厂方法
实例工厂方法(先实例)
单例模式
策略模式 DEMO (Spring的Resource接口就是一个策略接口 )
代理模式 DEMO proxy (Hibernate的延迟加载)
为真正的对象创建一个包装,可以提升性能,改善功能
简单做法,为每个类创建一个代理类
更好做法: 采用JDK动态代理,运行时创建JAVA类; DEMO
InvocationHandler接口
采用CGLIB代理,一样
CGLIB比JDK动态代理的功能强得多
门面模式 new HibernateTemplate() DEMO
方便,但失去部分灵活性
为了弥补灵活性不足的问题,HibernateTemplate提供了
execute(Hibernate<T> )... 命令模式
命令模式 Hibernate命令接口 DEMO
步骤:
拷Jar包
配置文件(放到src下)(2.0以前语义约束全部都是采用DTD的,2.0既有DTD形式,也有Schema形式,2.5,3.0改用了Schema,如果不需要使用Spring的高级功能,可以依然采用DTD作为约束)
name="dfd , dfdf" bean的别名
alias="" bean的别名
(前提是那个bean类必须要有一个 无参数的构造器)
(只要类有Setter方法,就可以配置Property, 并且这个Setter方法只能有一个参数)
BeanFactory的创建成本低,适合于内存比较小的应用研究
ApplicatinContext功能很完,在javaEE PC机通常使用这,
ClassPathXmlApplicationContext
<!-- 只要这个实现类有setter,我们就可配置property元素 -->
<!--
如果setter方法的形参类型是:
标量类型:基本类型,String,日期等,可以用value属性为该setter方法传入实参值。
复合类型, 可以系统类型、自定义类型:通常用ref属性将容器中另 一个Bean作为实参传入。或者使用嵌套Bean。
数组:
集合: <list> <set> <props>
Map: <map>
依赖注入
设值注入 <property />
构造注入 <bean ><constructor-arg /> </bean>
IoC(以前,第个Bean的属性都应该由程序来主动设置
spring,由Spring容器负责调用,原来叫控制反转)
嵌套Bean不能被容器直接访问,所以没有id
value ref bean list/set/map/props 分别代表Bean实例的种属性值
props (propertis类,一个特殊的Map类) 映射数组 用 list
Spring容器创建Bean的方式:
1.通过构造器 (<constructor-arg ../> 或者 无参数的构造器)
2.通过静态工厂方法
a) <constructor-arg > 传入值
3. 通过实例工厂方法
a) 实例工厂方法与静态工厂方法只有一点不同,调用静态工厂方法只需使用工厂类,而实例工厂方法则使用工厂实例(配置静态工厂方法时指定静态工厂类,配置实例工厂方法时指定工厂实例)
entry 另一种写法
<entry key="1" value="6565656656" />
single:单例模式,当容器创建时就会创建
spring的bean 可以是任何的java对象
Bean的作用域
1. singleton - 当ApplicationContext初始化时,
容器会自动创建Bean实例,并一直缓存着它们。
以后每当程序需要该Bean时,直接返回已有的Bean。
2. prototype - 以后每次程序请求获取该Bean时,Spring容器临时地创建Bean实例。
程序每请求获取一次,Spring容器就会创建一个Bean实例。
如果不指定Bean的作用域,Spring会使用默认的作用域singleton
3.request
4.session
5.global session
获取容器的引用
我们可能的习惯是:总是先获取Spring容器,再获取容器中的Bean。
但在有些情况下,我们可能已经获取了容器中的Bean,反过来想通过Bean来获取容器。
BeanFactoryAware
ApplicationContextAware
它们都用于获取Spring容器。
IoC(Inverse of control) 反转控制
DI(Dependency Ijection) 依赖注入
spring两个核心:
IoC
AOP
获取getter 方法
PropertyPathFactory 工具类,特殊的工厂
BeanFactory spring容器 是... 的父接口
FactoryBean 工厂Bean应该实现的接口,当我们把其部署到容器中后,程序通过getBean*(方法去获取FactoryBean,
注入其他Bean的属性集(成员变量):
就是获取其他的Bean的成员变量(静态/非静),
用的是FieldRetrievingFactory
一般情况:
targetBeanName
propertyPath 确定指定获取指定Bean的哪个属性值
<bean id="son1" class="...PropertyPathFactory">
<!-- 确定目标Bean,表明son1 bean来自哪个Bean属性-->
<property name="targetBeanName" value="person">
<!-- 确定属性表达式,表明son1 bean来自目标Bean的哪个属性-->
<property name="propertyPath" value="son">
</bean>
<bean id="pa"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetObject">
<!-- 目标Bean不是容器中已经存在的Bean ,而是如下嵌套Bean -->
<bean class="org.crazy.spring.Player" >
<property name="name" value="这是一个名字"></property>
</bean>
</property>
<!-- 确定属性表达式,表明pa bean来自目标Bean的哪个属性 -->
<property name="propertyPath" value="name" />
</bean>
System.out.println(app.getBean("pa"));
注入方法返回值:
当需要获取Bean的实例方法返回值时,必须指定两个属性:
targeObject:确定目标Bean,可以是容器中的已有的Bean ref=
targetMethod:确定目标方法,确定获取目标Bean哪个方法的返回值
如果需要获取静态方法的返回值:
targetClass value=
targetMethod
调用其他Bean 的任意方法,就是获取其他Bean的任意方法(静态/非静态)的反回值
用的是:MethodInvokingFactoryBean,
如果要为目标方法确定参数,要用arguments属性值
spring默认有个规则,总是先初始化主调Bean,然后再初始化依赖Bean
depends-on=""
自动装配:
autowire
当且仅当property属性的name属性值和ref属性值相同时,可以正常使用byteName自动装配策略
(autowire-candidate="false" //设置此bean不作为自动装配的对象)
依赖检查:
默认不进行依赖检查
Bean的销毁过程,生命周期行为
---创建实例
---注入依赖关系
(Bean初始化过程)
---调用afterPropertiesSet
---调用init-method <利用这个,密码加密>
---对外提供服务
(Bean销毁之前的行为)
---调用destroy
---调用destroy-method
---Bean实例被销毁
1.可以使用配置文件配置 bean.xml <bean destroy-method="close".. </beans>
2.可以让vo类实现 DisposableBean接口 void destroy() throws Exception
a) 两种方法没有本质区别,Spring可以自动检测容器中的DisposableBean,在销毁Bean实例之前,spring容器会自动调用此Bean实例的destroy方法
b) 实现接口污染了代码,是侵入式设计,不推荐使用
《如果上面两种方法都用了。容器会先执行DisposableBean接口中定义的方法,然后执行destroy-method属性指定的方法》
ctx.registerShutdownHook() ; //为sproin容器注册关闭钩子
如果容器中很多Bean 都需要指定特定的生命周期行为,则可以利用<beans >元素的defalut-init-method defalut-destroy-method 方法。其作用类似于<bean >元素的init-method destroy-method
协调作用域不同步的Bean 用cglip包
使用<lookup-method ../>
name
bean
用schcame简化配置
p: 相当于 property
util:
Sprijg涉及的对象:
Spring容器 容器后处理器
容器中的Bean Bean 后处理器(仅仅对容器中的Bean 做后处理,不返回客户端,所以不需要ID)
(后处理器都是对Spirng功能的扩展)
只要把的处理器布置到容器中,并采用ApplicatinContext 作为容器,后处理器就自动起作用。
Bean 后处理器,需要实现 BeanPostProcessor 8.1
代理初始化之后的后处理
@param 代表后处理之前的原来的Bean对象
@return 代表处理之后Bean对象,可以完全被改掉
容器后处理器,需要实现 BeanFactoryPostProcessor
配置C3P0数据源 `DEMO 8.1 PropertyOverrideConfigurer DEMO
资源访问 DEMO
Resource接口 相当于 策略接口
xxxResource相当于 不同算法的实现
FileSystemResource
ClassPathResource
ApplicationContext继承了ResourceLoader接口,因此ApplicationContext可用于获取
它实际上就是策略模式的Context类,它会负责为资源访问选择策略。
实际上,当你程序需要访问某个资源时,你根本没必要主动访问,完全可以让Spring容器将资源注入到你的程序中。
启动AOP:
xmlns:aop=""
<aop:aspectj-autoproxy />
@Aspect //定义切面Bean
@Before("execution(* org.crazyjava.test.GunDog.eat(..))")
//定义方法的增强处理。括号里的两个点代表可以有任意多个形参
//上面是@Before(value="execution(* org.crazyjava.test.GunDog.eat(..))")的简写
切面(Aspecdt)
连接点(Joinpoint)
增强处理(Adbice)//处理有"around" "before" "after" "afterReturning"等类型
切入点(Pointcut)
引入
目标对象
AOP代理
织入
@Before增强处理的限制:
不能阻止目标方法的执行
不能访问、修改目标方法返回值
(before增强处理执行时,目标方法还没获得执行的机会,所以无法访问目标方法访问值)
@AfterReturning:
参数:
poincut (相当于value)
returning //可以访问目标方法返回值,不能改变目标方法的返回值,也不能阻止目标方法的执行
@AfterThrowing
当目标方法执行引发了未处理异常进,此方法将获得执行
当目标方法实现了接口时, Spring AOP所生成的AOP代理其实就是JDK动态代理。
当目标方法没有实现接口时, 无法使用JDK动态代理,此时Spring AOP所生成的AOP代理其实难副就是
CGLIB代理
@After
不管目标方法是否完成,都会执行@After增强处理,而@AfterReturning增强处理只要在目标方法成功完成后才会织入
一般用来释放资源
@Around
它可在目标方法之前插入任何处理代码,也可在目标方法之后插入任何处理代码,
而且它可以轻松访问、修改目标方法的返回值,甚至可以完全阻止其执行
此方法一个形参必须是ProceedingJoinPoint类型(至少包含一个形参)
ProceedingJoinPoint的常用方法说明:
getArgs()
getSignature() 获取被增强的目标方法的方法签名
getTarget():获取目标对象。
getThis() : 获取生成的AOP代理
Object proceed() :回调目标方法 , 返回值就是原目标方法的返回值
Object proceed(Object[] arguments) :回调目标方法
定义切入点表达式的语法:
execution: 功能最强大。
target:要求目标对象必须是某个类的实例。
bean:要求只对Spring容器中的某个Bean增强。很简单、实用
args:用于对目标方法的形参进行限制。
让增强处理方法可以访问到目标方法的实参。
Hibernate 与 Spring 整合 门面模式 DEMO
1.Spring容器可以管理SessionFactory
2.HibernateTemplate类 (门面模式) JpaTemplate类也是一样的用
3.通过使用HibernateCallback接口(命令接口)
//可以避免HiberanteTemplate灵活性的不足的问题。
//因为在该方法中可使用Hibernate原生的Session,
4.HibernateDaoSupport DEMO (YeekuHibernateDaoSupport是一个扩展,因为本身不能分页)
MVC框架与Spring整合的关键在于:
数据库 → SessionFactory →(注入) DAO组件 → Service组件 → Action
如何让MVC控制器的访问Spring容器中的业务逻辑组件。
一旦MVC控制器可以访问Spring容器中的业务逻辑组件,
剩下的业务逻辑组件、DAO组件、它们已经形成了一个整体。
1. =============声明式的方式启动Spring容器===============
如果我们在Web应用中使用Spring,将更简单。
我们可以用声明式的方式来创建Spring容器。
ContextLoaderListener - 配置成Listener就行了。(策略模式)
ContextLoaderPlugIn 是跟struct1整合的
ContextLoaderServlet - 必须配置成load-on-startup的Servlet。
也是要做一件事情:让Web应用初始化时,初始化Spring容器。
但是,如果Web服务器支持Listener(Servlet 2.3 / jsp 1.2才有),
Web服务器只支持Servlet
如果希望让MVC框架去初始化
也是策略模式。策略接口是ContextLoader。
如果Web应用声明式的方式初始化Spring容器完成,
我们可以在Servlet、JSP中这样访问它:
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(application);
2. =============增加Struts 2的支持===============
3. =============把Struts 2的Action交给Spring容器管理===============
A。只要把Struts2 的Spring插件复制到Web应用的WEB-INF/lib目录下即可。
Spring的事务管理
-----------JDBC事务--------------
Connection.setAutoCommit(false);
sssssss
sdsf
sdfsf.sd
conn.commit()
conn.rollback
-----------Hibernate事务--------------
Session.beginTransaction
sssssss
sdsf
sdfsf.sd
tx.commit()
tx.rollback
-----------JPA事务--------------
em.getTransaction().begin
sssssss
sdsf
sdfsf.sd
em.getTransaction().commit()
em.getTransaction().rollback
-----------JTA全局事务--------------
UserTranscation tx = ctx.lookup("javax.transction.UserTransaction")
tx.begin()
可以是跨多个数据库的持久化访问。
tx.commit()
tx.rollback
发现一个需要解决的问题:
要做一件事情:管理应用的事务。
随着应用所采用的持久化技术的变化,事务控制的实现代码(不同的算法)是不同的。
——正好采用策略模式。
策略接口:PlatformTransactionManager
不同算法的策略实现类:XxxTransactionManager
Context类:它负责为客户端选择策略实现类。
——是因为我们在配置文件中选择了策略实现类。
客户端面向策略接口编程,这样客户端就可以在不同的算法实现之间自由切换。
接下来,是否应该把事务控制代码“插入(横切)”到每个业务组件、的业务方法的代码中。
Spring自己并没有提供事务的实现,
它所有的事务控制,它只是对原有事务的包装。
Spring是否支持JTA事务?
Spring自己其实并没有事务功能,它的作用是允许开发者面向PlatformTransactionManager接口编程,
或者直接通过配置来管理事务。
——应用程序就可以在底层事务之间自由切换。
事务的事务管理,本质上只是AOP的应用方便。
Spring和DWR的整合
DWR有一个创建器:spring
复制DWR JAR包。
配置DWR的核心控制器
增加DWR的配置文件。
由于需要Struts 2同时使用,所以要在struts.xml文件“放过”所有向DWR的请求。