首页 > 代码库 > Spring

Spring

Spring

主要内容:

  1. 面向接口(抽象)编程的概念与好处
  2. IOC/DI的概念与好处

a)     inversion of control

b)     dependency injection

  1. AOP的概念与好处
  2. Spring简介
  3. Spring应用IOC/DI(重要)

a)     xml

b)     annotation

  1. Spring应用AOP(重要)

a)     xml

b)     annotation

  1. Struts2.1.6 + Spring2.5.6 + Hibernate3.3.2整合

a)     opensessionInviewfilter(记住,解决什么问题,怎么解决)

  1. Spring JDBC
  2. 场景:用户添加
  3. 好处:灵活
  4. 把自己new的东西改为由容器提供

面向接口编程(面向抽象编程)

IOC(DI) 的好处

a)     初始化具体值

b)     装配

  1. 好处:灵活装配
  2. FAQ:不给提示:

Spring IOC配置与应用

a)     window – preferences – myeclipse – xml – xml catalog

b)     User Specified Entries – add

                 i.          Location:       spring-beans-2.5.xsd

                ii.          URI: spring-beans-2.5.xsd

               iii.          Key Type: Schema Location

              iv.          Key:              http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

  1. 注入类型

a)    Spring_0300_IOC_Injection_Type

b)     setter(重要)

c)     构造方法(可以忘记)

d)     接口注入(可以忘记)

  1. id vs. name

a)     Spring_0400_IOC_Id_Name

b)     name可以用特殊字符

  1. 简单属性的注入

a)     Spring_0500_IOC_SimpleProperty

b)    <property name=… value=http://www.mamicode.com/….>

  1. <bean 中的scope属性

a)     singleton 单例

b)     proptotype 每次创建新的对象

  1. 集合注入

a)     很少用,不重要!参考程序

  1. 自动装配

a)     byName

b)     byType

c)     如果所有的bean都用同一种,可以使用beans的属性:default-autowire

  1. 生命周期

a)     lazy-init (不重要)

b)     init-method destroy-methd 不要和prototype一起用(了解)

  1. Annotation第一步:

a)    修改xml文件,参考文档<context:annotation-config />

10. @Autowired:帮你从容器中找一个相同属性的bean,注入

a)    默认按类型

b)    如果想用byName,使用@Qulifier

c)     写在private field(第三种注入形式)(不建议,破坏封装)

d)     如果写在set上,@qualifier需要写在参数上

@Autowired

public void setUserDAO(

@Qualifier("userdao1")UserDAO userDAO) {

this.userDAO = userDAO;

    }

@required是在编译时先检查xml

 

  1. @Resource(重要)

a)     加入:j2ee/common-annotations.jar

b)    默认按 名称,名称找不到,按类型

c)    可以指定特定名称

d)     推荐使用

e)    不足:如果没有源码,就无法运用annotation,只能使用

f)     但是这样的话,还是需要在xml文件中去申明bean

 

使用component就可以让容器在包里自己寻找相应需要注入的bean,而不需要自己手动去配置。

 

  1. @Component @Service @Controller @Repository

默认下,会被当做组件被容器所接收

 

a)    初始化的名字默认为类名首字母小写

b)     可以指定初始化bean的名字

<context:component-scan base-package="xby" />

配置文件会从包里从上向下搜索,遇到@component的类就会将它加入到容器里,同时设置它的key是类名首字母小写

 

Xml的优势在没有源码的时候,可以在xml里做相应的修改。实际开发中使用注释开发效率高。

 

13.@Scope:

Singleton:单例

Prototype:多例

Request

Session

 

14.构造之后和销毁之前

@PostConstruct = init-method;

@PreDestroy = destroy-method;

 

什么是AOP

  1. 面向切面编程Aspect-Oriented-Programming

a)     是对面向对象的思维方式的有力补充

b)    1.写死的话,不便于修改

c)    2.继承父类 extends一旦父类发生变化,子类一定要相应的修改。

d)    3.组合 implement 在实现了相应接口后,可以相互组合。

e)    代理里有哪些方法是根据接口里的方法来的,接口里有哪些方法,代理就有哪些方法。代理对象会把所有的共有接口传进去,顺带把方法和方法的参数一起传进去,然后代理对象会把自己的业务逻辑和被代理对象的方法传进去。代理对象会先执行自己的方法,然后调用自己的invoke方法,这个方法就会调用被代理对象的方法,这就是实现了切面编程。

  1. Spring_1400_AOP_Introduction
  2. 好处:可以动态的添加和删除在切面上的逻辑而不影响原来的执行代码

a)     Filter

b)     Struts2的interceptor

  1. 概念:

a)     JoinPoint:在哪里加入

b)     PointCut:joinpoint的集合

c)     Aspect(切面):指的是逻辑切面

d)     Advice:指的是建议被加入的逻辑

e)     Target:被代理对象

f)      Weave:织入

代理:只要被代理的对象实现了一个接口,JDK就可以使用InvocationHandler和proxy来完成代理。但是如果被代理对象没有实现了接口,spring就会使用cglib直接操作二进制码来完成代理。

Spring AOP配置与应用

  1. 两种方式:

a)     使用Annotation

b)     使用xml

  1. Annotation

a)     加上对应的xsd文件spring-aop.xsd

b)     beans.xml <aop:aspectj-autoproxy />

c)     此时就可以解析对应的Annotation了

d)     建立我们的拦截类

e)     用@Aspect注解这个类

f)      建立处理方法

g)     用@Before来注解方法

h)     写明白切入点(execution …….)

i)      让spring对我们的拦截器类进行管理@Component

  1. 常见的Annotation:

a)     @Pointcut

b)     @Before

c)     @AfterReturning

d)     @AfterThrowing

e)     @After

f)      @Around

  1. 织入点语法

a)     void !void

b)     参考文档(* ..)

  1. xml配置AOP

a)     把interceptor对象初始化

b)     <aop:config

                i.          <aop:aspect …..

  1. <aop:pointcut
  2. <aop:before

---------------------------------------------------------------------------------------

<bean id="Log" class="xby.aop.Log"></bean>-------------------------切面逻辑类

<aop:config>

        <aop:pointcut expression="execution(public * xby.dao.impl..*.*(..))" id="servicePointcut" />

            <aop:aspect id="LogAspect" ref="Logb">

                <aop:before method="before" pointcut-ref="servicePointcut"/>

            </aop:aspect>            

</aop:config>

在aspect前的pointcut是全局的,可以被所有的aspect使用,而在aspect内部的pointcut是aspect自己的,只能自己用。

Aspect的ref是代表——附加逻辑的代理类

before的point-cut代表的是前面定义好的pointcut。

 

Pointcut其实就是你可以将附加的逻辑所加到的地方;

Aspect其实就是附加的逻辑切面。

---------------------------------------------------------------------------------------

<bean id="Log" class="xby.aop.Log"></bean>

<aop:config>

    <aop:aspect id="LogAspect" ref="Log">

         <aop:after method="after" pointcut="execution(public * xby.dao.impl..*.*(..))"/>

</aop:aspect>            

</aop:config>

上面的表达也是一样的。

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService service = (UserService)ctx.getBean("userService");

service.add(new User());

程序一开始调用add()-à发现它符合execution(public * xby.dao.impl..*.*(..))

à然后又发现有一个切面aspect-à接着就调用了proxy去做了代理,给它附加了代理逻辑。

 

 

 

 

 

 

 

 

Spring整合Hibernate

  1. Spring 指定datasource

a)     参考文档,找dbcp.BasicDataSource

                i.          c3p0

               ii.          dbcp

             iii.          proxool

b)     在DAO或者Service中注入dataSource

数据源(Data Source)是提供某种所需要数据的器件或原始媒体。顾名思义,数据的来源。在数据源中存储了所有建立数据库连接的信息。就像通过指定文件名称可以在文件系统中找到文件一样,通过提供正确的数据源名称,你可以找到相应的数据库连接。

c)     在Spring中可以使用PropertyPlaceHolderConfigure来读取Properties文件的内容(占位符)

  1. Spring整合Hibernate

a)     <bean .. AnnotationSessionFactoryBean>

                i.          <property dataSource

               ii.          <annotatedClasses

b)     引入hibernate 系列jar包

c)     User上加Annotation

d)     UserDAO或者UserServie 注入SessionFactory

---------------------------------------------------------------------------------------

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"

        destroy-method="close">

        <property name="driverClassName" value=http://www.mamicode.com/"com.mysql.jdbc.Driver" />

        <property name="url" value=http://www.mamicode.com/"jdbc:mysql://localhost:3306/spring" />

        <property name="username" value=http://www.mamicode.com/"root" />

        <property name="password" value=http://www.mamicode.com/"root" />

    </bean>

---------------------------------------------------------------------------------------

<bean id="SessionFactory"

class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

        <property name="dataSource" ref="dataSource" />

        <property name="annotatedClasses">

            <list>

                <value>xby.model.User</value>

            </list>

        </property>

        <property name="hibernateProperties">

            <props>

                <prop  key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>

                <prop key="hibernate.show_sql">true</prop>

            </props>

        </property>

    </bean>

<bean id="txManager"

        class="org.springframework.orm.hibernate3.HibernateTransactionManager">

        <property name="sessionFactory" ref="SessionFactory" />

</bean>

<tx:annotation-driven transaction-manager="txManager"/>

---------------------------------------------------------------------------------------

  1. 声明式的事务管理

a)     事务加在DAO层还是Service层?

业务逻辑层处理事务不能加在实现层,否则回滚时会出现不一致性。用spring 来做声明式事务管理,就不需要去关心try catch,只需要关心自己的业务逻辑。Spring 会帮你做事务管理,类似回滚之类。

b)     annotation

                i.          在需要事务的方法上加:@Transactional

               ii.          需要注意,使用SessionFactory.getCurrentSession 不要使用OpenSession

---------------------------------------------------------------------------------------

 

<bean id="txManager"

        class="org.springframework.orm.hibernate3.HibernateTransactionManager">

        <property name="sessionFactory" ref="SessionFactory" />

</bean>

 

<tx:annotation-driven transaction-manager="txManager"/>

---------------------------------------------------------------------------------------

 

c)     @Transactional详解

                i.          什么时候rollback

  1. 运行期异常,非运行期异常不会触发rollback
  2. 必须uncheck (没有catch)
  3. 不管什么异常,只要你catch了,spring就会放弃管理
  4. 事务传播特性:propagation_required
  5. read_only

Transactional配置:

Propagation=

  1. Mandatory:方法执行时必须有一个transaction存在
  2. Nested:方法执行时在已经存在的transaction中内嵌一个,不影响外部事务;
  3. Never:不能有事务;
  4. Not_supported:方法执行时,如果有事务,就给他挂起
  5. Required:方法执行时,当前有事务就用它,没有就新创建;
  6. Required_new:方法执行时,如果有事务,就将存在的事务给它挂起,自己重新生成一个新的事务;
  7. Support:随当前事务,有就有,没有就没有。

   ReadOnly=true效率比较高;public void getUser(int id)这时候就可以设置为只读

   Rollbackfor:什么情况下回滚,默认为RuntimeException

No Rollbackfor

d)    xml(推荐,可以同时配置好多方法)

---------------------------------------------------------------------------------------

<aop:config>

<aop:pointcut expression="execution(public * xby.service..*.*(..))"

            id="bussinessService" />

<aop:advisor advice-ref="txAdvice" pointcut-ref="bussinessService" />

</aop:config>

<tx:advice id="txAdvice" transaction-manager="txManager">

<tx:attributes>

<tx:method name="getUser" read-only="true" />

<tx:method name="add*" propagation="REQUIRED" />

</tx:attributes>

</tx:advice>

---------------------------------------------------------------------------------------

e)     HibernateTemplate

HibernateCallback、

HibernateDaoSupport(不重要)

                i.          设计模式:Template Method

----------------------------------------------------------------------------------

<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">

<property name="sessionFactory" ref="SessionFactory"></property>

</bean>

----------------------------------------------------------------------------------

               ii.          Callback:回调/钩子函数

             iii.          第一种:(建议)

  1. 在spring中初始化HibernateTemplate,注入sessionFactory
  2. DAO里注入HibernateTemplate
  3. save写getHibernateTemplate.save();

             iv.          第二种:

  1. 从HibernateDaoSupport继承
  2. 必须写在xml文件中,无法使用Annotation,因为set方法在父类中,而且是final的

f)      spring整合hibernate的时候使用packagesToScan属性,可以让spring自动扫描对应包下面的实体类

 

JDBC
  你需要做的第一事情是你与想要使用的 DBMS 建立一个连接。这包含 2 个步骤:装载驱动程序并建立连接。
1)装载驱动

你想要使用 JDBC-ODBC 桥驱动程序, 可以用下列代码装载它:

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

你的驱动程序文档将告诉你应该使用的类名。例如, 如果类名是 jdbc.DriverXYZ ,你将用代码以下的代码装载驱动程序:

Class.forName("jdbc.DriverXYZ");

你不需要创建一个驱动程序类的实例并且用 DriverManager 登记它,因为调用 Class.forName 将自动加载驱动程序类。  

加载 Driver 类后,它们即可用来与数据库建立连接。

2)建立连接
  第二步就是用适当的驱动程序类与 DBMS 建立一个连接。下列代码是一般的做法:          Connection con = DriverManager.getConnection(url, "name", "Password");

如果你装载的驱动程序识别了提供给 DriverManager.getConnection 的 JDBC URL ,那个驱动程序将根据 JDBC URL 建立一个到指定 DBMS 的连接。正如名称所示,DriverManager 类在幕后为你管理建立连接的所有细节。除非你是正在写驱动程序,你可能无需使用此类的其它任何方法,一般程序员需要在此类中直接使用的唯一方法是 DriverManager.getConnection。

DriverManager.getConnection 方法返回一个打开的连接,你可以使用此连接创建 JDBC statements 并发送 SQL 语句到数据库。在前面的例子里,conn 对象是一个打开的连接,并且我们要在以后的例子里使用它。

 rs.next(); -- 从查询出来的集合中拿出了一条数据:表示的集合表中的第一个对象。
rs.getInt(int index); 通过索引来获得查询结果集中的某一列的值
rs.getInt(String columName); 通过列名来获得查询结果集中的某一列的值
rs.getInt(1)//等价于rs.getInt("id");
rs.getString(2)//等价于rs.getInt("name");

例子:

String  sql = "select * from people p where p.id = ? and p.name = ?";
preparedstatement  ps  = connection.preparestatement(sql);
ps.setint(1,id);
ps.setstring(2,name);
resultset rs = ps.executequery();

Spring