1. POJO(Plain OldJava Objects)简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB混淆所创造的简称
2. dom4j比jdom强大,都是Java的XML API
3. PO:persistenceobject
4. spring中读取xml文档的部分模拟代码
<beans> <bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl[f1] " /> <bean id="userService" class="com.bjsxt.service.UserService[f2] " > <property name="userDAO" bean="u"[f3] /> </bean>
</beans> |
private Map<String , Object> beans = new HashMap<String, Object>();
public ClassPathXmlApplicationContext() throws Exception { SAXBuilder sb=new SAXBuilder();
Document doc=sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml")); //构造文档对象 Element root=doc.getRootElement(); //获取根元素HD List list=root.getChildren("bean");//取名字为disk的所有元素 for(int i=0;i<list.size();i++){ Element element=(Element)list.get(i); String id=element.getAttributeValue("id"); String clazz=element.getAttributeValue("class"); Object o = Class.forName(clazz).newInstance(); System.out.println(id); System.out.println(clazz); beans.put(id, o);
for(Element propertyElement : (List<Element>)element.getChildren("property")) { String name = propertyElement.getAttributeValue("name"); //userDAO String bean = propertyElement.getAttributeValue("bean"); //u Object beanObject = beans.get(bean);//UserDAOImpl instance
String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1); System.out.println("method name = " + methodName);
Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]); m.invoke(o, beanObject); } } } |
5. 配置文件中property标签一般都对应后台程序里面的set方法。
6. IOC 也称为DI 控制反转[f4] 依赖注入
7. spring两大核心:IOC和AOP
8. IOC容器作用:
实例化具体bean
动态装配
9. AOP支持什么:
安全检查
管理transaction
10. RC 版, Release Candidate 发布候选版
11. dist版,distribution发布版
经常会有Helios RC2版本这样的,这里RC就是Release Candidate,意为发布候选版本。
还有时会有Eclipse Ganymede SR2 Packages (v 3.4.2) ,这里SR就是:修正版或更新版,修正了正式版推出后发现的Bug。
另外,常见软件中常会见到这些版本:
Trial:试用版,软件在功能或时间上有所限制,如果想解除限制,需要购买零售版。 Retail:零售版。
Free:免费版。
Full:完全版。
Alpha:内部测试版,通常在Beta版发布之前推出。
Beta:测试版,正式版推出之前发布的版本。以上两种测试版本Bug可能较多。
Final:正式版,软件的正式版本,修正了Alpha版和Beta版的Bug
SR:修正版或更新版,修正了正式版推出后发现的Bug。
Pro:专业版,需要注册后才能解除限制,否则为评估版本。
Plus:加强版。
Delux:豪华版。Plus版和Delux版区别不大,比普通版本多了一些附加功能
12. spring中的bean.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-4.0.xsd">
<bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl"> </bean>
<bean id="userService" class="com.bjsxt.service.UserService"> <property name="userDAO" ref="u"[f5] /> <!-- <ref bean=”u”></ref> --> </bean>
</beans> |
13. 尽量用ApplicationContext,是BeanFactory的上层,实现了更多的方法。
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); //BeanFactory ctx = new ClassPathXmlApplicationContext("beans.xml"); |
14. spring初步调用代码
package com.bjsxt.service;
import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.bjsxt.model.User;
//Dependency Injection //Inverse of Control public class UserServiceTest {
@Test public void testAdd() throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
// BeanFactory ctx = new ClassPathXmlApplicationContext[f6] ("beans.xml");
UserService service = (UserService)ctx.getBean("userService");
User u = new User(); u.setUsername("zhangsan"); u.setPassword("zhangsan"); service.add(u); }
} |
15. commons-logging.jar包是使用spring的必备包。
16. 如果在xml文档中不给提示,则可以window-preferences-myeclipse-filesand editors-xml-xml catalog-add。加入对于的xsd后缀的文件,然后选择Schema location,最后在key值后面加上location最后面的文件名(eg:/spring-context-4.0.xsd)。如果自己不配置,myeclipse就会去网上找。
17. IOC:注入类型
1) setter 调用了setXXX方法
2) 构造方法(用的少)
3) 接口注入(基本不用)
<bean id="userService" class="com.bjsxt.service.UserService"> <!-- <property name="userDAO" ref="u" />[f7] --> <constructor-arg><ref bean="u"/></constructor-arg>[f8] </bean> |
18. JMS (Java Message Service)
19. IOC:id vs. name
name可以用特殊字符
<bean id[f9] ="u" class="com.bjsxt.dao.impl.UserDAOImpl"> </bean> |
20. IOC:简单属性的注入,对应简单数据类型(int等)的属性而言的,很少用
<property value[f10] =……> |
21. IOC:bean标签中scope属性,默认情况就是单例
1) singleton单例,不论拿多少次都是同一个对象.
2) prototype每次创建新的对象
22. IOC:集合注入(很少用)具体看参考文档
23. IOC:自动装配,bean标签的autowire属性。默认值为no,不自动装配。
自动装配对应的问题是:我们不手动在bean标签中加property标签的情况下,要装配的类怎么去找对应的bean的问题
1) byName bean的name属性和要装配的类中的属性名一样的情况下自动装配
2) byType 会按类型来查,但是同样类型有多个bean的情况下就会报错
3) 如果所有的bean都用同一种autowire属性值,则可以在beans标签中添加defalt-autowire属性
24. IOC:生命周期
1) lazy_init[f11] :是bean标签的一个属性,如果不加lazy_init=”true”,只要context初始化,一new出:newClassPathXmlApplicationContext("beans.xml"),里面的所有类就初始化了;如果加上lazy_init=”true”,context初始化的时候不初始化这个类,什么时候用的时候(getBean)再初始化。(不重要)
2) init-method destroy-method :类里面有初始化方法和destoy方法,容器初始化这个类的时候要调用初始化方法,容器关闭的时候要调用destory[f12] 方法,这个时候可以配置这两个bean标签的属性。不要和prototype[f13] 一起用(了解)
3) beans标签中也有一个default-lazy-init属性
25. IOC前面讲的配置都可以转换为Annotation,下面将是IOC的Annotation配置。
1) Annotation第一步:
a) 修改xml文件:bean标签还是需要的,只是不需要bean标签里面的ref标签。也就是用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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:annotation-config/>[f14] <bean></bean> </beans> |
2) @Autowired:自动装配,加在要注入属性的set方法上面。用的不多容易产生各种各样的问题
a) 默认按类型by type
b) 如果想用byName,使用@Qulifier[f15]
c) 写在private field(第三种注入形式)(不建议,破坏封装)
d) 如果写在set上,@qualifier需要写在参数上
e) 还可以加属性required=false。注入的时候如果没有,也可以。
3) @Required,实例化的时候必须注入,运行之前就检查,可以提早发现错误。写不写均可。如同@override,写了的话可以提早发现错误,在编译期间就能发现错误。
4) @Resource[f16] (重要)importjavax.annotation.Resource;本来要找common.annotation.jar包,但是j2se jdk中好像也已经部分实现了这些标准。故目前先不加,后面再说。
a) 加入:j2ee/common-annotations.jar
b) 默认按名称,名称找不到,按类型
c) 可以指定特定名称
d) 推荐使用
e) 不足:如果没有源码,就无法运用annotation,只能使用xml[f17]
5) @Component[f18] @Service @Controller@Repository
这4个注解目前基本上可以当做是一样的,没什么太大区别。
a) 初始化的名字默认为类名首字母小写
b) 可以指定初始化bean的名字(getBean的时候用的参数)
6) @Scope加在类外面,bean的生存范围。
7) @PostConstruct = init-method; @PreDestroy = destroy-method;加在bean方法前面
26. JSRs:JavaSpecification Requests 在jcp(javaCommunity Process)网站上可以查看具体JSR
27. Common annotations原本是Java EE 5.0(JSR 244)规范的一部分,现在SUN把它的一部分放到了Java SE 6.0中.随着Annotation元数据功能(JSR 175)加入到Java SE 5.0里面,很多Java 技术(比如EJB,Web Services)都会用Annotation部分代替XML文件来配置运行参数(或者说是支持声明式编程,如EJB的声明式事务), 如果这些技术为通用目的都单独定义了自己的Annotations,显然有点重复建设, 所以,为其他相关的Java技术定义一套公共的Annotation是有价值的,可以避免重复建设的同时,也保证Java SE和Java EE 各种技术的一致性
28. AOP:面向切面编程 Aspect-Oriented-Programming
29. 给一个方法前后加逻辑:
源码上加;继承该类,重写该方法;组合,新类里面有个原来对象的引用。
30. 动态代理: jdk proxy invocationhaddler 具体参考
1) InvocationHaddler 是代理实例的调用处理程序实现的接口。要实现这个接口,横切代码加在实现这个接口的类里面。
2) Proxy 可以通过newProxyInstance静态方法来产生代理实例。要动态代理,要先产生被代理对象,然后通过上面实现了InvocationHaddler接口的类里面的构造方法注入,最后new出代理对象,接着就可以根据代理对象动态调用被代理对象的类的接口的方法。
31. new Class[f19] []{target.class}也可以表示为”对象.getClass().getInterfaces()”、表示Class类型的数组,里面装的是通过:类名.forName()、类名.class拿到的Class对象。
32. 动态代理: 需要在多个方法上面都要加业务逻辑的时候,就可以考虑动态代理
代理:在被代理的对象调用方法的前后做一些事情例如权限、审查、事务、日志、检测方法性能(时间)、try catch等。实现InvocationHaddler这个接口,在实现里面的方法的时候在方法内部加一些事务等的处理,然后在通过invoke方法调用实际要执行的方法。
动态:只需写一个处理方法,不需要在每个方法前后都去加同样的处理,然后可以通过Proxy类的newProxyInstance静态方法来获取初始化的代理对象,最后可以调用被代理对象的类的接口[f20] 的方法。
33. 代理也有和junit一样的好处:测试的时候可以在方法的前后加一些处理,结束的时候可以很容易的删掉(虽然没有junit那么方便)。
在高度一点,我们可以把interceptor也就是实现InvocationHaddler这个接口的类的信息放在配置文件中,通过配置文件控制是否要添加这个过滤,或者过滤的信息是什么等。spring就是这么干的。
34. spring背后的实现就是使用了JDK的动态代理(当然前提是类实现了一个接口),如果类没有实现接口,spring也能产生动态代理(直接生成二进制码,用继承)。
注:我们平时写程序的时候一般都推荐面向接口编程。
35. sevelet的filter,struts的intercept,动态代理。这些都是AOP的思考方式。
36. spring aop annotation:
1) 配置文件:
<?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: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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd "> <context:annotation-config/> <context:component-scan base-package="com.bjsxt"/> <aop:aspectj-autoproxy/>[f21] </beans> |
2) 把逻辑织入[f22] 到原来的方法当中去。需要写个如下的切面类
需要加入aspectjrt.jar和aspectjweaver.jar两个jar包
package com.bjsxt.aop;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component;
@Aspect[f23] @Component[f24] public class LogInterceptor { @Pointcut[f25] ("execution(public *[f26] com.bjsxt.dao..*.*(..))[f27] ") public void myMethod(){};
@Before[f28] ("myMethod()") public void before[f29] () { System.out.println("method before"); }
@Around[f30] ("myMethod()") public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable { System.out.println("method around start"); pjp.proceed();[f31] System.out.println("method around end"); }
} |
3) 概念:
a) JoinPoint 在哪些个点上需要把切面逻辑加进去
b) PointCut 切入点集合,可以一下子定义好多切入点
c) Aspect(切面)类加上去的逻辑就是切面,加了@Aspect的类
d) Advice 可以理解为切面上的逻辑,加了@Aspect的类里面的方法
e) Target 被代理对象
f) Weave 织入
37. spring4.0的aop的通知:@Before @Around等的注解表示时需要引入aopalliance[f32] .jar包,低级版本好像不用。
38. 如果切面在没有实现接口的类上面,spring直接操作cglib-nodep.jar二进制码的类库来实现代理。本来需要引入cglib[f33] -nodep.jar,但是spring4.0不需要,从spring3.2开始就被打包在spring-core.jar里面了。
39. GLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。
它底层使用字节码处理框架ASM。其原理是,生产一个要代理类的子类,子类覆盖要代理的类的所有不是final的方法。
它比使用java反射的JDK动态代理要快。通常情况下,你可以使用JDK的动态代理创建代理,当你要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。
40. aop xml 示例代码
<context:annotation-config /> <context:component-scan base-package="com.bjsxt"/>
<bean id="logInterceptor" class="com.bjsxt.aop.LogInterceptor"></bean> <aop:config>
<aop:aspect id="logAspect" ref="logInterceptor"> <aop:before method="before" pointcut="execution(public * com.bjsxt.service..*.add(..))" /> </aop:aspect> </aop:config> |
41. spring aop配置:一般使用前两种
1) 使用Annotation。
2) 使用xml 用的最多,和ioc不一样,这个面向切面编程在后续处理比较重要,所以annotation加在源码上的就不方便,xml用起来就方便点。
3) 使用spring自带的Annotation
4) 使用AspectJ
42. spring3以前只需引入一个spring.jar即可,spring为了让用户按需添加,分了好多小模块。spring4.0要添加好多jar包。
spring初步整合hibernate
1) Spring中指定datasource[f34]
a) 参考文档,找dbcp[f35] .BasicDataSource
<bean id="dataSource[f36] " class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver "/> <property name="url" value="jdbc:mysql://localhost:3306/spring "/> <property name="username" value="root"/> <property name="password" value="flf1989317"/> </bean> |
spring中和数据库连接的时候如上配置(后面可以把参数写入propertise文件),spring内部调用org.apache.commons.dbcp.BasicDataSource,连带的调用了commons.pool.jar。
i. c3p0 spring和hibernate中都可以配
ii. dbcp
iii. proxool
spring中指定datasource有上面三种实现连接池的方法。数据库连接池配在spring和hibernate中都可以。讲了applicationServer后,大多数情况下通过JNDI配在applicationServer里面。
b) 在DAO或者Service中注入dataSource
c) 在Spring中可以使用PropertyPlaceHolder[f37] Configure来读取Propertise文件的内容
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer[f38] "> <property name="locations"> <value>classpath:[f39] jdbc.properties</value> </property> </bean>
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${[f40] jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> |
2) Spring4.0与Hibernate4.3.0的初步整合
需要的jar包:(其他的包用到再加,log4j、slf4j等)
spring-aop-4.0.0.RELEASE.jar | aop有关 |
spring-beans-4.0.0.RELEASE.jar | bean有关 |
spring-context-4.0.0.RELEASE.jar | Spring中的注解有关 |
spring-core-4.0.0.RELEASE.jar | 里面集成了cglib,不需要添加cglib-nodep.jar |
spring-tx-4.0.0.RELEASE.jar | 里面集成了跟数据库操作有关的,不需要添加spring.dao.jar或者spring. transaction.jar包 |
spring-expression-4.0.0.RELEASE.jar |
|
spring-orm-4.0.0.RELEASE.jar | 跟hibernate有关,没有hibernate好像也要加 |
spring-jdbc-4.0.0.RELEASE.jar |
|
spring-web-4.0.0.RELEASE.jar | 包含Spring整合struts2的时候,要在web.xml中配置监听器[f41] 的类。 |
| Spring4没有spring.jar包,不需要导入 |
commons-logging-1.1.3.jar | Spring中好像必须加的,处理日志的 |
junit-4.11.jar | 单元测试 |
hamcrest-core-1.3.jar | 单元测试 |
aopalliance.jar | 跟spring aop有关 |
aspectjrt.jar | Spring aop annotation有关 |
aspectjweaver.jar | Spring aop有关 |
commons-dbcp-1.4.jar | Spring连接数据库有关,dbcp即数据库连接池 |
commons-pool-1.6.jar | 数据库连接池 |
common-annotation.jar | Jdk里面已经集成了部分common-annotation里面的内容,先不用加,如果出现了jdk里面没有的,再考虑加 |
mysql-connector-java-5.1.26-bin.jar | Mysql驱动 |
hibernate-release-4.3.0.Final里面的lib目录下的required目录下的全部jar包 | Hibernate必须的包 |
bean.xml中的sessionFactory配置示例
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean[f42] "> <property name="dataSource" ref="dataSource" /> <property name="annotatedClasses"> <list> <value>com.bjsxt.model.User</value> </list> </property>[f43] <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.MySQL5[f44] Dialect </prop> <prop key="hibernate.show_sql">true</prop>[f45] </props> </property> </bean> |
43. Spring注解加在set方法上面,hibernate注解加在get方法上面。
44. bean.xml文件中,datasource被注入到了sessionfactory中;useDAOImpl中sessionfactory被注入了进去;userservice中useDAO被注入了进去。
45. 使用annotation进行声明式事务管理
1) 事务加在DAO层还是Service层?看具体情况,最好加在service层,因为service方法里面可能处理多个调用数据库的方法,这时如果加在DAO层,回滚可能会不彻底。
2) 在方法上面加@Transaction,同时要在xml文件中要做相应改变
<!-- from the file context.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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!-- this is the service object that we want to make transactional --> <bean id="fooService" class="x.y.service.DefaultFooService"/>
<!-- enable the configuration of transactional behavior based on annotations --> <tx:annotation-driven[f46] transaction-manager[f47] ="txManager"/><!-- a PlatformTransactionManager is still required --> <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /[f48] > </bean>
<!-- other <bean/> definitions here -->
</beans> |
46. @Transaction的属性propagation[f49]
@Transactional(propagation=Propagation.REQUIRED)
事务的传播特性:Propagation的枚举值
REQUIRED,默认值。方法1中调用了方法2,方法1上面加了事务,方法2上面就不需要加事务了。
MANDATORY[f50] ,当前方法要执行,必须要有一个transaction,也就是说上层的调用就应该加Transaction。如果没有,则报错。
NESTED,内嵌Transaction,内部事务回滚会不会影响外部事务,具体情况具体测试或详查文档。
NEVER,这个方法要执行,必须不能有事务,有事务就报错
NOT_SUPPORTED,这个方法要执行,必须不能有事务,如果有事务就将事务挂起,执行完该方法,在继续事务
REQUIRES_NEW,创建一新的事务,如果当前有事务就先挂起
SUPPORTS
47. @Transaction的属性isolaion, readOnly[f51] ,timeOut,[f52] rollbackFor[f53] , rollbackForClassname,noRollbackFor[f54] , noRollbackForClassname。
48. 使用xml进行声明式事务管理,文档中有详细说明。
spring的事务配置:有了下面xml配置,java文件中@Transaction注解就可以去掉,xml文档中<tx:annotation-driventransaction-manager="txManager"/>就可以去掉
<!-- this is the service object that we want to make transactional --> <bean id="fooService" class="x.y.service.DefaultFooService"/>
<!-- the transactional advice (what happens; see the <aop:advisor/> bean below) --> <tx:advice[f55] id="txAdvice" transaction-manager="txManager"> <!-- the transactional semantics... --> <tx:attributes> <!-- all methods starting with get are read-only --> <tx:method name="get*" read-only="true"/>[f56] <!-- other methods use the default transaction settings (see below) --> <tx:method name=""/> </tx:attributes> </tx:advice>
<!-- ensure that the above transactional advice runs for any execution of an operation defined by the FooService interface --> <aop:config> <aop:pointcut[f57] id="fooServiceOperation" expression="execution( x.y.service.FooService.*(..)[f58] )"/> <aop:advisor advice-ref="txAdvice"[f59] pointcut-ref="fooServiceOperation"/> </aop:config>
<!-- don't forget the DataSource --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/> <property name="username" value="scott"/> <property name="password" value="tiger"/> </bean>
<!-- similarly, don't forget the PlatformTransactionManager --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager[f60] "> <property name="dataSource" ref="dataSource"/> </bean>
<!-- other <bean/> definitions here -->
</beans> |
49. spring 整合hibernate的时候可以使用packagesToSacn属性,让spring自动扫描对应包下面的实体类
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="annotatedClasses"> <list> <value>com.bjsxt.model.User</value> <value>com.bjsxt.model.Log </value> </list> </property>[f61] <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.MySQL5Dialect </prop> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean> |
50. spring对于hibernate在编程上有些简化的方式(封装了try catch等),主要是使用:HibernateTemplate(建议)、HibernateDaoSupport[f62] (不重要)。这些类在spring中主要处理关于hibernate事务的异常、回滚等问题,在spring组合hibernate4的时候已经不推荐使用了,因为hibernate4已经将事务做的很好了,直接调用hibernate自己的事务管理即可,spring不在去管hibernate的事务这一块了。
51. 设计模式:Template Method
52. HibernateTemplate:(spring针对hibernate4中已经没有该接口)
1) 在spring中初始化HibernateTemplate[f63] ,将注入sessionFactory到HibernateTemplate里面。
2) 接着DAO里面再注入HibernateTemplate
53. callback回调函数,钩子函数。简单点说就是:函数里面调用函数,外面函数写好了,里面的函数也给了接口,自己只需写里面的函数即可,里面的函数就是回调函数。外面函数的参数可以传一个实现了里面函数的接口的函数对象,里面函数的参数可以是里面自己的变量。
54. HibernateDaoSupport:(spring针对hibernate4中已经没有该类)
继承该类,然后this.getHibernateTemplate().save(XXX)或者this[f64] .save()。
同时要注入HibernateTemplate[f65] 或者sessionFactory。
另外注意HibernateDaoSupport中的setSuperHibernateTemplate(HibernateTemplatexxx)方法
55. 尽量能少用继承就少用继承。
SSH整合:
56. model层实体类:充血模型(逻辑处理代码多),贫血模型(逻辑处理代码少)。
eg:可以在user类中写个isexits()方法检查是否存在,为什么这个方法可以放在user里面呢?因为要检查是否存在,肯定是有user对象已经存在,逻辑上符合情理。
在user类中增加save就不太合适,当然也可以sava自己或者将方法写成静态方法。
编程习惯:同样逻辑的代码只能写一遍。user中的isexits()方法可以调用service层里面类的isexits(User xxx)方法。
57. 一个事务尽量放在一个方法中处理,比如说用户注册中:检查数据库名字是否存在和增加用户到数据库,按理来说应该是一个事务,如果在service中作为两个方法处理就会多次打开数据库连接,所以可以写一个add方法,如果用户名已经存在可以往外抛出一个自己定义的异常,根据是否有异常抛出来确定是否已经被注册,或者直接存进数据库即可。
58. java web项目用到的类库都加在web-INF目录下的lib目录下。通过buildpath直接引用进来在myeclipse中部署的时候也可以看到,但是项目jar包不会部署到tomcat中。Junit包就可以通过buildPath引入进来。
59. Junit中的org.junit.Assert类,里面有很多静态方法,可以很方便的来调用。如果输入参不符合预期时会抛出AssumptionViolatedException,默认的BlockJUnit4ClassRunner及其子类会捕获这个异常并跳过当前测试,显示为蓝色,方法没通过。如果符合预期,则显示为绿色,通过测试,跳过当前测试。如果出现红色,则是代码有问题。
60. junit测试的时候可以添加数据,但是每个测试方法结束的时候要恢复现场,删除掉数据,以免影响其他测试方法。
spring加hibernate测试的之后可以自动回滚,即加入数据测试完后可以自己清除。
61. Assert.fail(“string s”)这个方法里面的字符串s在测试失败的时候在测试窗口会显示出来。
62. service层和Dao层的方法可以不对应[f66] ,service层里面是业务逻辑,Dao层只是数据库逻辑。比如service层加一个add方法,增加对象进来不一定要保存到数据库,所以Dao层不一定要有add方法将其存进数据库。如果要保存进数据库,我也可以换成个名字,更适合操作数据库的名字比如save方法等。再比如service层一个方法可能要调用几个Dao层方法。
另外Dao层也可以多一些更好的方法出来,比如getNameById等。
63. 在被调用的Dao层,要根据实际情况产生更好的方法。比如检查名字存不存在数据库中,我们不用写isexit方法,可以写更有意义的getNameById等方法,让service层自己调用该方法去判断存不存在。
64. 另外在service层未必只用到一个Dao的实现。比如要加入日志logDao等,一个service还可以引用多个Dao的实现。解决了有些项目service成看起来和Dao层的方法基本一样,只是方法里面调用Dao层同样的方法,为什么还要写service层的问题?或许我们以后要在service层加日志方法等,到时候可以方便的加入日志的Dao层实现。
实际项目中很多这么干的,效率等因素促使service层和dao层方法一样。没有很好的去考虑实际情况,要不要多点其他方法,这个方法会不会显得多余等。
65. java文件右键重构里有个Extract Interface..抽取接口功能。很给力。
66. mvc中的m指的是model[f67] -模型,模型表示企业数据和业务规则,例如ssh中的“实体+service+dao层+数据库”就是一个model。
struts是控制器 c,由filter和action层组成;
jsp是视图v。
67. 纯纯的action里面不写业务逻辑,if else等,直接调用service层方法就可以返回要求的值。这才是mvc中真正的C。实际项目开发中很多action里面有逻辑。
68. ssh中:
springIOC:struts2的filter生成action的时候要交给spring来管理,spring可以注入service;service也交给spring来管理,spring可以注入dao;dao中的sessionfactory也可以由spring来注入;
spring aop:spring的声明式事务管理将service层中每个方法都可以当做事务来处理;
69. spring和struts2整合可以参考struts的参考文档中的springplugin。spring参考文档中也有相关设置方法。
在web.xml中增加关于spring的listener(监听器)[f68] 标签
<listener>[f69] <listener-class>org.springframework.web.context.Context[f70] LoaderListener[f71] </listener-class> </listener> |
作用:在webapplication启动的时候就启动spring容器,然后去找里面的配置文件,把里面的对象全都给初始化出来,容器就产生了。
配置文件位置的指定,可以在web.xml中如下配置:
<context-param>[f72] <param-name>contextConfigLocation</param-name> <param-value[f73] >/WEB-INF/applicationContext*[f74] .xml</param-value> </context-param> |
70. 没有配置spring的时候service层对象不能注入到action层中去,action类的初始化是由struts负责。
71. struts+spring配置在一块的时候,struts要求spring将service层对象注入进来。
72. 要将action配置配到spring里面来,让spring把action管理起来,然后让struts2去找spring要这些action的生成。
原来action对象的生成是由struts2自己new出来的,现在可以交给spring来处理,@component。记得加上@Scope(property[f75] )。
加上相应的jar包:struts2-spring-plugin-2.3.14.jar
struts2配置文件中action标签的name属性值,程序会根据这个值去容器里面找这个bean。
有人可能认为在spring中已经初始化了action bean,这样的话再struts配置文件中要不要action标签后面的class属性?当然要,现在是根据struts标签中的name属性找,以后如果换成type等,找不到对应的bean怎么办。
73. struts-plugin.xml(struts2-spring-plugin-2.3.14.jar里面的文件)文件内容解析:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts> <bean type[f76] ="com.opensymphony.xwork2.ObjectFactory"name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />
<!-- Make the Spring object factory the automatic default --> <constant name="struts.objectFactory" value="spring" />[f77]
<constant name="struts.class.reloading.watchList" value="" /> <constant name="struts.class.reloading.acceptClasses" value="" /> <constant name="struts.class.reloading.reloadConfig" value="false" />
<package name="spring-default"> <interceptors> <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/> </interceptors> </package> </struts> |
74. struts2读配置文件中常量的顺序:struts-default.xml——struts-plugin.xml——struts.xml——struts.properties——web.xml。
75. DTO:DataTransfer Object
VO:Value Object
这种对象跟实体对象的区别是:实体对象反应在数据库里面,这种对象只是在用到它的时候临时的去保留一些值。eg:密码验证有两次密码输入,而数据库中只有一个密码;校验码;搜索时的上架时间范围起始时间和结束时间可能和产品的上架时间不能匹配上等。
76. dto的概念不单单只是存在于form表单这个概念上,在整个层次体系结构中,service层和实体层到dao层可能也存在dto这个概念。eg:从数据库中拿出来的这些数据,这些数据是一个分页数据,一共有6条,每页有2条数据,前台页面会显示相应的共多少页,有没有上一页下一页等内容,如果返回来的只包含这两条数据,其他的页数等数据怎么返回回来,所以dto层返回回来的数据,往往可以单独封装成一个对象,这个对象既包含返回的2条记录,又包含了我们想要的其他信息,这也是一个中dto。
77. 可以新增一个web.dto、vo或者dto层。里面的类可以加Vo、Dto、Info或者FormBean后缀。这样的话可以在action层里面加入dto层对象,并设置好相应的set、get方法。在struts中验证。也可以在实体类中增加一个构造方法,将dto对象通过构造方法传入实体类对象。
78. egb1.0、egb2.0、egb2.1都不好用,但是概念很好,大牛根据这些概念自己弄出来了spring
、hibernate、struts等,ejb3.0又把ssh中的概念引入了进来。
79. j2ee架构设计中不能省略jsp和实体类层(实体类也可以省略,但是省略了那就有点离谱了),所以架构设计中最重要的就是要解决jsp设计(也就是实际设计中的界面原型)和实体类的设计(也就是数据库表)。
80. 设计师第一步绝对是确定需求,对应j2ee来说就是界面原型;第二部就是domainmode(实体类),可以直接写类,也可以建立数据库表,实际当中很多人往往都是建数据库表;其它的层就好说了。
81. action中的set、get方法的作用:set方法可以将表单中的值存入Action类中;get方法调用体现在struts标签可以调用get方法将数据显示在页面上。struts配置文件中的方法里面调用service层。
82. spring和struts整合的时候,在action中用注解的话,action中的属性set方法前不用加@Resource,会被自动注入,而且默认是按name匹配注入的的。这个在struts文档中spring-plugin里面的设置里面是默认的。即struts.objectFactory.spring.autoWire=name。
另外action中的@component(“xxx”)可以不写。spring-plugin帮我们扫描struts.xml,帮我们在产生一个action对象(该对象名字可能是action属性name值,不在spring容器中)。
@Scope(“prototype”)不写也可以。默认Scope就是prototype[f78] 。可以加一个构造方法来检查scope的值,构造方法里面在控制台输出点东西,然后部署多次访问看控制台输出即可。
综上所述:action的产生过程完全归struts或者说归spring-plugin管,即可以说action对象在struts容器中,不用在action里面加注解,如果写了就平白无故的在spring容器里面多了个action对象。spring里面装了负责给action用的那些个对象,action产生完了,会自动的去spring容器里面找这些service、manage、dao这些个bean。
实际中action中的注入可能有三种常用方法:什么注解都不加;在private 属性前面加@Resource(“XXX”);或者按类型来(struts.objectFactory.spring.autoWire=type)。
83. 经过仔细研究,struts的action可以由spring来产生。要想让spring来产生action,可以将struts.xml中的action标签里面的class属性配置成:具体action类上面的@Component(“XXX”)里面的XXX。这次action上面就可以写@Component(“xxx”)了,struts通过action的class属性配置找到这个Component,这次去找的时候就是去spring容器里面找的。这时候action里面注入的东西就要加@Resource,因为action是spring产生的。另外不要忘了加@Scope(“prototype”)。
现在就有两种产生action的方式,spring产生action的好处是可以通过spring的测试方式来测试,这是就自动的注入进来,如果用struts产生action的方式,得通过struts的方式后它才能自动的注入,不好测。
84. hibernate中的load方法拿出来的是个代理[f79] ,事务加在service层,load方法调用完毕事务就结束了,session接着关闭,然后在jsp页面调用load方法的拿到的数据,这样后台就会报错:could not initializeproxy – no session。
解决方法:可以将load方法换为get方法;可以将session的范围扩大,session一般在事务完成后关闭,扩大可以通过spring提供的filter[f80] (名字为:openSessionInView[f81] 。配置在web.xml中)完成;其他方法。
85. openSessionInView的filter需要一个sessionFactory的bean,所以配置文件中要有一个bean标签id为sessionFactory。如果不叫sessionFactory,则可以在filter标签中加一个init-param标签:
<init-param> <param-name>sessionFactoryBeanName</param-name> <param-value>XXX</param-value> </init-param> |
86. 如果在bean.xml中把事务配置去掉,则openSessionInView的filter配置就会引起错误: Write operationsare not allowed in read-only mode……
servicec层不加事务配置并且不加openSessionInView的filter配置,则事务边界在dao的实现层(save等方法上)。
openSessionInView的fiter拦截到一个方法的时候,如果这个方法没有配置事务(dao里面的save方法不算事务配置),它认为这个事务就是只读的,所以save等插入数据的方法就会报错。
87. ssh乱码问题,可以在struts.xml配置name等于i18nEncoding的常量来解决。这个在struts2.1.6里面是个bug,同样不能解决问题。这时可以添加一个filter解决问题,每过来一个请求都将里面的字符集转换成自己想要的字符集,加在struts的filter前面[f82] ,不过用不着自己写,spring已经帮我们写好这个filter:org.springframework.web.filter.CharacterEncodingFilter.class ,将这个filter[f83] 配置在我们的web.xml中即可。
88. spring下的自动化测试,spring下有一个自己的测试框架:springtestcontext。
不会破坏数据库现场,测试之后数据库数据恢复正常。要继承AbstractTransactionalJUnit4SpringContextTests[f84] 这个类。
参考网页:http://www.ibm.com/developerworks/cn/java/j-lo-spring25-test/
89. 直接使用Junit测试Spring程序存在的不足:
90. opensessioninviewinterceptor与opensessioninviewfilter解决同样的问题,但是配置不一样。
91. SpringJDBCTemplate和hibernateTemplate
92. 为了方便测试分层系统的某个层面的是否正确,可以在调用的下层写简单方法,比如:只打印一些字符,不添加任何逻辑。具体也可以在dao层不连接数据库,直接打印字符串等。
93. spring3.0的getbean方法支持泛型,不用加强制类型转换了。具体查询api文档
94. spring3.0又增加了一种配置方式javaconfig,以前有xml和annotation两种。
java based bean metadata也就是说以前写配置可以写成xml,现在写配置可以写成一个java类,里面的属性注入也有响应的方法@Value,另外也可以使用jdbcproperties文件里面的东西等,另外一个bean属性注入另外一个bean也有对应的格式。
95. SpEL:spring expression language
ExpressionParser, SpelExpressionParser,EvaluationContext,Standard EvaluationContext, parseExpression,
可以和配置文件结合在一起,
96. 如果能把一个符合java语法的字符串当做java语句来运行的话,这样的语言就是动态语言,可惜java目前做不动这一点,python、javascript[f85] 、ruby等语言就可以。
97. System类里面有个getProperty方法,关于系统的语言、国家等信息都可以通过该方法拿出来。
[f1]dao写成一个接口,service层调用dao层接口编程。利用多态我们可以写daoimpl层,具体要换底层数据库的时候我们只需换daoimpl层的类即可。
[f2]service层,可以读取来new service对象,不过service对象里面还包括了属性—dao层对象的引用,用property标签内容表示dao层对象信息,可以读取并通过set方法放入service对象中
[f3]动态装配。将service层和dao层(具体是daoimpl层)一一对应的装配到一起。
或者叫做注入。将dao注入到service里面
注入,一个类的属性写在配置文件中,在这个类对象生成的时候注入进来
[f5]等价于下面的ref标签,两者二选一即可
[f6]类层次关系:BeanFactory——>ApplicationContext——>ClassPathXmlApplicationContext
[f7]setter注入
[f8]构造方法注入,同时要在类中用构造方法初始化属性值
如果构造方法参数类型一样,就可以在配置文件中设置索引或类型来区别。具体是在constructor-arg标签加index或type属性。详情可以查参考文档
[f9]id可以换成name
[f10]其值为简单数据类型
[f12]要测试destory,则要把ApplicationContext ctx =new ClassPathXmlApplicationContext("beans.xml");里面的ApplicationContext换成ClassPathXmlApplicationContext,因为前面的类没close方法,容器关闭不了。在web中“关闭”会有别的程序处理,不用担心。
[f14]向 Spring容器注册
AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、
PersistenceAnnotationBeanPostProcessor 以及RequiredAnnotationBeanPostProcessor这 4个BeanPostProcessor。
注册这4个 BeanPostProcessor的作用,就是为了你的系统能够识别相应的注解
[f15]@Qulifier加在要注入的参数前面
@Autowired加在要被注入的属性的get方法前面
public void setUserDAO(@Qualifier("u")UserDAO userDAO) {
this.userDAO = userDAO;
}
[f17]这句话的意思是程序已经交付了,没有源码,要更改的话只能使用xml,而不能在源码上加annotation。不过大多数情况下都有源码。
[f18]配置文件中:<context:component-scanbase-package="com.bjsxt"></context:component-scan>
可以替代其中的的bean标签
要在类前面加:@Component
@Resource也要加
[f21]意思是可以使用aspectj注解的方式来定义一个spring的AOP。
自动帮我们产生代理。spring容器启动过程中,扫描到一个东西需要产生代理,它就会帮助我们产生代理。
spring内部的实现由aspectj实现。aspectj是一个专门用来产生代理或者面向切面编程的框架。spring使用了它。
[f22]weaver:织工
[f24]参考前面的ioc,意思这个类也要初始化。
[f25]把后面产生织入点的语句命名为下面的方法:myMethod(),方便后面的@Before等的调用,要不每次都要写一遍,麻烦
[f26]可以是void或者!void
[f28]在切入点前调用下面的方法
[f29]方法名随意,跟上面的注解没有关系
[f30]前后都加方法
[f32]联盟
[f33]Code Generation Library
[f34]实现了javax.sql.DataSource接口,需要xml中配置一下参数
javax.sql.DataSource该工厂用于提供到此 DataSource 对象所表示的物理数据源的连接。作为 DriverManager工具的替代项,DataSource对象是获取连接的首选方法。
DataSource 接口由驱动程序供应商实现。共有三种类型的实现:
- 基本实现 - 生成标准的 Connection 对象
- 连接池实现 - 生成自动参与连接池的 Connection 对象。此实现与中间层连接池管理器一起使用。
- 分布式事务实现 - 生成一个 Connection 对象,该对象可用于分布式事务,大多数情况下总是参与连接池。此实现与中间层事务管理器一起使用,大多数情况下总是与连接池管理器一起使用。
[f35]数据库连接池
[f37]占位符,${}
[f38]占位符属性配置器对象
[f39]src目录路径,也就是将jdbc.properties文件放在src目录下
[f41]<listener>
<listener-class> org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
[f42]这是和hibernate4整合的。
和hibernate3整合的时候有两种写法:
xml的话就把4改成3;
annotation的话,则就要改为hibernate3.annotation.AnnotationSessionFactoryBean
为什么4中没有注解的写法,因为hibernate4把通过xml和annotation拿到session的方法统一为一个了。hibernate3中有两个。
[f43]这一块可以换成实体类的xml映射配置,现在是annotation配置
<propertyname="mappingResources">
<list>
<value>product.hbm.xml</value>
</list>
</property>
[f44]注意hibernate4里面这里要加5
[f46]注解驱动的事务管理
[f48]将sessionfactory注入进来,无处不在的注入啊
[f50]mandatory,强制的
[f52]事务时间太长的话就终止掉
[f53]在什么情况下回滚,默认出runtimeException的情况下,可以更改其值,确定回滚条件。
[f54]出什么异常了不回滚
[f55]事务传播配置
[f57]定义切面
[f58]切面是这个目录下的所有方法
[f60]用到的是datasource的事务管理,没有和hibernate关联起来
[f61]可替换为
<property name="packagesToScan ">
<list>
<value>com.bjsxt.model</value>
</list>
</property>
packagesToScan意思是那些包配置了实体类,spring帮我们扫描下,写一个包名即可,不然要添加很多实体类
[f62]其中的save等操作数据库方法内部实现有调用HibernateCallBack对象当参数。
[f63]hibernate4中已经事务已经封装的比较好了,spring就没有关于事务的HibernateTemplate(里面是和session有关的方法)这个类了
[f64]内部实现调用了前面的this.getHibernateTemplate(),不过该方法好像有点问题
[f65]不能使用Annotation注入,因为HibernateDaoSupport里面的setHibernateTemplate等方法都是final,不能在子类中重写并用annotation来注解。所以只能用xml注入。
但是xml注入会产生一个问题,如果好多daoImpl都要注入,那在想xml中就要配置很多。
这个问题可以在DAOImpl层写一个抽象的类,继承HibernateDaoSupport,只在xml中注入一次,然后每个DaoImpl不去直接继承HibernateDaoSupport,而是继承自己写的抽象类即可(这个解决方案有点问题,实现层类用注解,注入的对象用xml,匹配不到一块,报错。可以在抽象类中使用setSuperHibernateTemplate(HibernateTemplate xxx)方法用注解的方式注入HibernateTemplate或者注入sessionFactory,用setSessionFactory(SessionFactoryxxx)方法。当然也可以将抽象类组合进实现层里面的类,不过这样就比较麻烦了,跟hibernateTemplate差不多了)。
或者在DAOImpl层写一个类,不去继承HibernateDaoSupport,将hibernatetemplate注入进来,实现层来继承它,类似hibernatetemplate方法,不用每次在daoImpl类中注入了。
[f66]数量和名字上都可以不对应,两层中方法不论谁多谁少都可以。
[f67]以前总以为只是实体entity。
[f68]让webApplication一启动就自动的加载配置文件,自动的把里面的bean初始化。
[f69]应用程序一启动,就会找我们的listener,listener就会找我们的配置文件,默认配置文件为:/WEB-INF/applicationContext*.xml
里面配置的就是一个spring容器,不包含action类的各种bean。action由struts或者spring-plugin产生。
[f70]web application context即项目名
[f71]重新加载的时候监听器就会起作用,然后读取配置文件,把里面的各种各样的bean初始化
[f72]当前整个应用的一个参数,上面那个listener启动的时候会去读这个参数,名字叫contextConfigLocation
[f73]里面的值也可以写成calsspath:beans.xml,也就是src目录下的beans.xml
[f74]一个模块写一个spring配置文件。可以引入多个spring配置文件。
[f75]多例,每个请求都会产生一个新的action
[f76]后面class的值是实现了type接口的类,class的值是spring工厂,这个spring工厂会自动找到监听器,然后找到配置文件,扫描里面的文件,把bean放到容器中。
[f77]一般的情况下需要一个action的时候,默认去找struts自己的工厂。这里配置了常量struts.objectFactory,这时候就去找名字为后面value值的那个工厂(上面已经配置好的),spring工厂
[f78]不是单例
[f80]在需要session的时候,只要session一打开,session会直到我们访问完的时候才关闭。
filter配置有前后顺序,该filter要配置在struts的filter前面,因为jsp数据调用要在struts处理之后。
[f81]字面意思是在视图中打开session,视图即jsp。
org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.class
[f82]跟openSessionInView的filter没有冲突,所以这只要在struts的filter前面即可。
[f83]记得设置filter中的<init-parm>标签
[f84]spring-test-4.0.0.RELEASE.jar 下面的org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests.class
[f85]里面的eval()函数