●什么是IOC(DI),有什么好处
·把自己new的东西改为由容器提供
1)初始化具体值
2)装配
·好处:灵活装配
·spring是什么 类与类之间的关系只要在xml中配置好,
调用ClassPathXmlApplicationContext的getBean方法,
就可以得到一个装配好的类的对象。
●简单项目搭建
·xml src目录下 beans.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="u" class="com.bjsxt.dao.impl.UserDAOImpl">
</bean>
<bean id="userService" class="com.bjsxt.service.UserService">
<property name="userDAO" >
<ref bean="u"/>
</property>
</bean>
</beans>
·引入spring包
1)spring-framework-2.5.6\dist\spring.jar 核心包
2)spring-framework-2.5.6\lib\jakarta-commons\commons-logging.jar 日志包
·使用时写明配置文件的完整位置 如果不写默认在src下找
ApplicationContext factory = new ClassPathXmlApplicationContext("cn/itcast/helloworld/beans.xml");
●spring的注入类型
·setter注入
在被注入的类写好成员变量的set方法,由容器调用此方法注入到类中。优点是可以在set方法中加入逻辑
<property name="userDAO" > 类中成员变量的名字
<ref bean="u"/> 要注入的对象
</property>
·构造方法注入
用构造方法的参数在构造方法中初始化此成员变量 优点是不用谢set方法
●bean中的id和name
<bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl">
<bean name="u" class="com.bjsxt.dao.impl.UserDAOImpl">
其实id和name是一样的 name里可以有一些特殊字符
●简单属性注入(少用)
在被注入的类写好成员变量(简单属性而非对象)的set方法
<property name="属性名" value="注入值" />
●bean的作用域
<bean id="" class="" scope="作用域">
scope可以取singleton单例 prototype一个bean定义对应多个实例
多用prototype
●集合注入
注入的成员变量是一个集合
<bean id="moreComplexObject" class="example.ComplexObject">
<property name="someList">
<list>
<value>a list element followed by a reference</value>
<ref bean="myDataSource" />
</list>
</property>
<property name="someMap">
<map>
<entry key="1" value="1"></entry>
<entry key="2" value="2"></entry>
</map>
</property>
<property name="someSet">
<set>
<value>1</value>
<value>2</value>
</set>
</property>
<property name="someProp">
<props>
<prop key="username">lijinfei</prop>
</props>
</property>
</bean>
●自动装配
<bean id="" class="" scope="" autowire="">
autowire为自动装配,可以为此对象自动装配其成员变量
·byName 找bean的name和成员变量的名字相同则初始化,名不同报错
·byType 找bean的class和成员变量的类型一样则初始化,多了报错
●延迟初始化bean
<bean id="" class="" lazy-init="true">
此时bean在applicationContext初始化时不初始化(new ClassPathXmlApplicationContext时)
●初始化时执行的方法指定 容器初始化bean的时候 调用
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
●结束时执行的方法指定 容器关闭的时候 调用
<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
●Ioc Annotation
<?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:annotation-config/>---------------------------------------------依赖注入注解解析器
</beans>
·@Autowired 用的不多
自动寻找对应类型的bean注入到该成员变量中
@Qualifier(value="beanName") 写于方法的参数前 指定被注入bean的name
·@Required 用的不多
这个标签标注的属性必须在配置注入
·@Resource(name="beanName") 常用
写于set方法前 或者属性前 将name对应的bean的对象注入到这个成员变量中
·@Component
<context:component-scan base-package="com.bjsxt"/>--------------------------自动类扫描注解解析器
此时xml中的bean都不写了,自动去com.bjsxt这个包中找。
然后用@Component(value="userDAO")注释每个bean类
value指明这个bean的name
·@Scope("prototype")
写于类前,说明此bean的适用范围
·@PostConstruct @PreDestroy
写于方法前,标明此方法在构造完成之后或容器销毁之前调用方法
●AOP
·Aspect-Oriented-Programming 面向切面编程
·使用Spring的AOP 先加入jar包 在spring/lib/aspectj下
在XML中加入
<beans xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<aop:aspectj-autoproxy /> <!--此时 可以用aspectj的annotation来注解需--!>--------------基于AOP的注解解析器
·想要生成没有实现接口的类的代理需要引入spring/lib/cglib/包
·Annocation
1)必须用@Component标注类或者为它配<bean>让Spring管理它
2)用@Aspect标注类为切面逻辑类
3)切入点表达式 6.2.3.4
任意公共方法执行 execution(public * * (..))
任何以set开始的方法执行 execution(* set*(..))
AccountService接口定义的任意方法的执行 execution(* com.xyz.service.AccountService.*(..))
在service包中定义的任意方法执行 execution(* com.xyz.service.*.*(..))
4)声明通知
@Before 注解一个方法为某(表达式表达的)方法的前置方法
@AfterReturning 注解一个方法为某方法正常结束后的后置方法
@AfterThrowing 注解一个方法为某方法 抛出异常后执行的方法
@After 注解一个方法为某方法无论是否正常结束的后置方法
@Around 注解一个方法为某方法前后都执行 详细参考说明文档6.2.4.5
5)例如
@Pointcut("execution(public * com.bjsxt.dao..*.*(..))")
private void myMethod(){}//定义了一个切入点表达式 名字为myMethod
@AfterReturning("myMethod()") //使用上面定义的切入点表达式
public void afterReturn(){
xxxxxxx
}
·XML
1)为切面类写bean让spring管理它
<bean id="logInterceptor" class="com.bjsxt.aop.LogInterceptor"><bean>
2)声明表达式并命名
用标签experession写明表达式和用id写明切面逻辑的名字 也可以放到aop:aspect中则仅当前aspect可用
<aop:config>
<aop:pointcut expression="execution(public * com.bjsxt.dao..*.*(..))" id="servicePointcut"/>
</aop:config>
3)声明切面
ref写明切面类 aop:before写明此类中的方法名和参考的表达式名 pointcut可以直接定义
<aop:config>
<aop:aspect id="logAspect" ref="logInterceptor">
<aop:before method="before" pointcut-ref="servicePointcut"/>
<aop:before method="before" pointcut="execution(public * com.bjsxt.dao..*.*(..))"/>
</aop:aspect>
</aop:config>
●Spring 整合 Hibernate
·Spring指定datasource
datasource是一个抽象的数据源 因为 数据源的种类很多 比如数据库
1)xml中写明数据源的bean
<bean id="myDataSource" 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="root" />
</bean>
然后在类中写好成员变量和get set方法标注@Resource 让spring注入 然后就可以使用此DataSource了
加入jar包 spring\lib\jakarta-commons\commons-dbcp.jar和commons-pool.jar和mySQL的jdbc驱动包
注意 做实验时建立好数据库和表再用spring对表进行操作
2)xml中写明数据源的bean 参数用占位符代替 需要时去properties文件中找
<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>
在src目录下建立jdbc.properties内容为
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root
·Spring 整合 hibernate
1)xml中
<bean id="SessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="annotatedClasses">
<list>
<value>com.bjsxt.model.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<!-- 还有自动建表等 -->
</props>
</property>
或者直接引入hibernate配置
<property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
</bean>
解释:
org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean为spring中支持hibernate的注解的类,在说明文档中没写。
dataSource参数 为hibernate设置数据库 ref参考了数据源的bean
annotatedClasses告诉hibernate哪些类是实体类(在类中用hibernate的注解@Entity标注)
并且用<property name="packagesToScan">
<list>
<value>com.bjsxt.model</value>
</list>
</property>
此时包内所有实体类会自动被扫描出
<!-- property name="mappingDirectoryLocations">当使用hbm时配置此项会自动扫描
<list>
<value>classpath:cn/itcast/xx/domain</value>
</list>
</property -->
hibernateProperties用来设置一些hibernate的参数(以前写在hibernate.propertites文件中的)
2)初始化过程中 由spring将datasource注给sessionfactory,将sessionfactory注给dao,将dao注给service。
调用过程中 service的add调用dao的add,dao的add调用sessionfactory的save.
3)由于在dao中使用sessionFactory是hibernate的东西所以要将hibernate的包都引入,参考hibernate笔记
·声明式的事物管理
1)事物的管理应该加在service层
1.1用spring的annotation给方法加事物 将sessionfactory注给事物管理类的bean
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory"/>
</bean>
还要加入
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
<tx:annotation-driven transaction-manager="txManager"/>
加入jar包spring\lib\cglib\cglib.jar
1.2使用@Transactional(propagation=Propagation.REQUIRED)
使用注释 会自动加上关于事物的业务逻辑遇到异常会自动回滚
REQUIRED表示,如果调用此方法的方法有事物则此方法调用是事物的一部分,如果没有则创建新事物 (事物的传播方式)
2)使用XML
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
<aop:config>
<aop:pointcut id="bussinessService" expression="execution(public * com.bjsxt.service..*.*(..))" /> 事物边界在service
<aop:advisor pointcut-ref="businessService" advance-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager"><!-- 更加细粒度控制事物(细到了方法) -->
<tx:attributes>
<tx:method name="get*" read-only="true"/> 这个方法是只进行读操作,其中不能向数据库插入更新数据
<tx:method name="add*" propagation="REQUIRED"/>如果调用此方法的方法有事物则此方法调用是事物的一部分,如果没有则创建新事物
</tx:attributes>
</tx:advice>
·HibernateTemplate、HibernateCallback、HibernateDAOSupport介绍
1)设计模式:Template Method 模板模式
callback:回调、钩子 就是在方法内部将自己的参数传给另一个函数让他实现,然后接着执行。
2)HibernateTemplate封装了sessionFactory,取好了session。可以直接使用这个对象的save方法。
首先在XML中生成HibernateTemplate类的bean并将sessionFactory注入
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="SessionFactory"></property>
</bean>
再将HibernateTemplate注入给dao类,dao类就可以用HibernateTemplate的类了。
●Spring 管理 struts2 其实是将spring作为插件 插入到struts2中
·在web.xml中加入监听器 使spring知道项目启动了,然后初始化所有的bean (<web-app>标签内)
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
<默认会找/WEB-INF/applicationContext.xml 初始化里面的bean 所以我们可以把beans.xml改个名 放到这个目录下>
</listener>
下面的配置可以更改配置文件的位置及名字 (<web-app>标签内)
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
或者这么写可以更改路径和名称:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans.xml</param-value> 这个就是到服务器的class目录里找beans.xml 在开发环境中就是src里的beans.xml
</context-param>
·加入jar包
/struts/struts2-spring-plugin.jar
·原理简析
在struts的action初始化的时候有自己的容器 初始化自己的bean(action),加入这个包后,
struts在调用自己的容器初始化bean时调用spring初始化bean,spring不仅把action注入到struts中,还把beans.xml中的文件全部注入好。
就是 根据action的名字,去容器中(此时是去spring容器中)找这个名字的bean,将它初始化。
·在action类写好@Component@Scope("prototype")和@Resource 由spring生成bean,然后再在struts.xml中的action的class写这个bean的名字而不写类
当struts启动时,会去spring中按bean的名字找到由spring初始化好的action。
·web.xml中配filter解决session范围问题,因为用load方法拿到的是代理对象,真正用到的时候才去数据库取,这时session关闭了,jsp调用getUsername方法才发语句,就取不了东西了。
解决方法 延迟session的关闭时间的配置
<filter>
<filter-name>openSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-parm> 这个参数指定spring中sessionFactory的名字,因为这个filter需要控制session
<param-name>sessionFactoryBeanName</param-name>固定写法
<param-value>sf</param-value> 自己写sessionfactory名
</init-parm>
</filter>
<filter-mapping>
<filter-name>openSessionInView</filter-name>ff
<url-pattern>/*</url-pattern>
</filter-mapping>
注意:使用这个filter必须在spring中配好声明事物管理Transactiona,否则这个filter认为此事物只读,不允许做增删改。
此filter必须配置在struts2的filter之前
·spring对于乱码的filter
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
<filter-mapping>
●拿到当前的spring容器
ApplicationContext ctx1 =
//new ClassPathXmlApplicationContext("cxf-servlet.xml");
WebApplicationContextUtils.getWebApplicationContext(getServletContext());