Spring学习
Spring简介
Spring是一个开源框架,最早由Rod Johnson创建,并在《Expert One-on-One:J2EE Design and Development》这本著作中进行了介绍。Spring是为了解决企业级应用开发的复杂性而创建的,使用Spring可以让简单的JavaBean实现之前只有EJB才能完成的事情。但Spring不仅仅局限于服务器开发,任何Java应用都能在简单性、可测试性和松耦合等方面从Spring中获益。
Spring核心
1.控制反转(IOC):以前传统的java开发模式中,当需要一个对象时我们,我们会自己使用new或者getInstance等直接或者间接调用构造方法创建一个对象,而在Spring开发模式中,Spring容器使用了工厂模式为我们创建了所需要的对象,我们使用时不需要自己去创建,直接调用Spring为我们提供的对象即可,这就是控制反转的思想。实例化一个java对象有三种方式:使用类构造器,使用静态工厂方法,使用实例工厂方法,当使用spring时我们就不需要关心通过何种方式实例化一个对象,spring通过控制反转机制自动为我们实例化一个对象。
2.依赖注入(DI):Spring使用Java Bean对象的Set方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程就是依赖注入的基本思想。
3.面向切面编程(AOP):在面向对象编程(OOP)思想中,我们将事物纵向抽象成一个个的对象。而在面向切面编程中,我们将一个个对象某些类似的方面横向抽象成一个切面,对这个切面进行一些如权限验证,事物管理,记录日志等公用操作处理的过程就是面向切面编程的思想。
spring优势
}1.依赖注入/控制反转(DI/IOC). 说白了就是根据配置文件动态组装复杂对象,实现了松耦合
}2.AOP(面向切面编程)
}3.提供简易的服务抽象
}4.集成管理各种框架
spring如何选用
版本
◦2.0(较广)
◦2.5(较广)
◦3.0(最新)
什么项目适合?
◦小项目亦可
◦中项目最适合
◦大型分布式项目(EJB)
项目中配置spring按照如下步骤实现即可:
1.去官方网站下载:http://www.springframework.org/
2.下载完成后,解压:
3.打开dist目录,将spring.jar添加到项目依赖库中,将lib/jakata-commons/commons-logging.jar加到项目依赖库中。
配置bean
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:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 配置一个 bean --> <bean id="helloWorld" class="com.atguigu.spring.helloworld.HelloWorld"> <!-- 为属性赋值 --> <property name="user" value="Jerry"></property> </bean> <!-- 配置一个 bean --> <bean id="helloWorld2" class="com.atguigu.spring.helloworld.HelloWorld"> <!-- 为属性赋值 --> <!-- 通过属性注入: 通过 setter 方法注入属性值 --> <property name="user" value="Tom"></property> </bean> <!-- 通过构造器注入属性值 --> <bean id="helloWorld3" class="com.atguigu.spring.helloworld.HelloWorld"> <!-- 要求: 在 Bean 中必须有对应的构造器. --> <constructor-arg value="Mike"></constructor-arg> </bean> <!-- 若一个 bean 有多个构造器, 如何通过构造器来为 bean 的属性赋值 --> <!-- 可以根据 index 和 value 进行更加精确的定位. (了解) --> <bean id="car" class="com.atguigu.spring.helloworld.Car"> <constructor-arg value="KUGA" index="1"></constructor-arg> <constructor-arg value="ChangAnFord" index="0"></constructor-arg> <constructor-arg value="250000" type="float"></constructor-arg> </bean> <bean id="car2" class="com.atguigu.spring.helloworld.Car"> <constructor-arg value="ChangAnMazda"></constructor-arg> <!-- 若字面值中包含特殊字符, 则可以使用 DCDATA 来进行赋值. (了解) --> <constructor-arg> <value><![CDATA[<ATARZA>]]></value> </constructor-arg> <constructor-arg value="180" type="int"></constructor-arg> </bean> <!-- 配置 bean --> <bean id="dao5" class="com.atguigu.spring.ref.Dao"></bean> <bean id="service" class="com.atguigu.spring.ref.Service"> <!-- 通过 ref 属性值指定当前属性指向哪一个 bean! --> <property name="dao" ref="dao5"></property> </bean> <!-- 声明使用内部 bean --> <bean id="service2" class="com.atguigu.spring.ref.Service"> <property name="dao"> <!-- 内部 bean, 类似于匿名内部类对象. 不能被外部的 bean 来引用, 也没有必要设置 id 属性 --> <bean class="com.atguigu.spring.ref.Dao"> <property name="dataSource" value="c3p0"></property> </bean> </property> </bean> <bean id="action" class="com.atguigu.spring.ref.Action"> <property name="service" ref="service2"></property> <!-- 设置级联属性(了解) --> <property name="service.dao.dataSource" value="DBCP2"></property> </bean> <bean id="dao2" class="com.atguigu.spring.ref.Dao"> <!-- 为 Dao 的 dataSource 属性赋值为 null, 若某一个 bean 的属性值不是 null, 使用时需要为其设置为 null(了解) --> <property name="dataSource"><null/></property> </bean> <!-- 装配集合属性 --> <bean id="user" class="com.atguigu.spring.helloworld.User"> <property name="userName" value="Jack"></property> <property name="cars"> <!-- 使用 list 元素来装配集合属性 --> <list> <ref bean="car"/> <ref bean="car2"/> </list> </property> </bean> <!-- 声明集合类型的 bean --> <util:list id="cars"> <ref bean="car"/> <ref bean="car2"/> </util:list> <bean id="user2" class="com.atguigu.spring.helloworld.User"> <property name="userName" value="Rose"></property> <!-- 引用外部声明的 list --> <property name="cars" ref="cars"></property> </bean> <bean id="user3" class="com.atguigu.spring.helloworld.User" p:cars-ref="cars" p:userName="Titannic"></bean> <!-- bean 的配置能够继承吗 ? 使用 parent 来完成继承 --> <bean id="user4" parent="user" p:userName="Bob"></bean> <bean id="user6" parent="user" p:userName="维多利亚"></bean> <!-- 测试 depents-on --> <bean id="user5" parent="user" p:userName="Backham" depends-on="user6"></bean> </beans>
2.通过注解扫描的方式
spring 2.5新增自动扫描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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 配置自动扫描的包: 需要加入 aop 对应的 jar 包 --> <context:component-scan base-package="com.atguigu.spring.annotation.generic"></context:component-scan> </beans> 配置<bean>的根本目的,就是让spring容器知道这个bean是要加载的。我们也可以通过注解来实现让spring知道哪些bean需要加载。 ◦@Service:标记业务层bean ◦@Controller:标记控制层,比如:struts中的Action ◦@Repository:标记数据访问组件,即DAO类 ◦@Component:当组件不好归类时使用该标记
AOP面向切面编程
如果说面向对象编程是关注将需求功能划分为不同的并且相对独立,封装良好的类,并让它们有着属于自己的行为,依靠继承和多态等来定义彼此的关系的话;那么 面向方面编程则是希望能够将通用需求功能从不相关的类当中分离出来,能够使得很多类共享一个行为,一旦发生变化,不必修改很多类,而只需要修改这个行为即 可。
AOP主要应用于日志记录,性能统计,安全控制,事务处理等方面。
AOP的内部实现都是通过动态代理来实现。动态代理有两种常见的方式:
1.JDK提供的代理生成方式(Proxy, InvocationHandle)
2.cglib 类库(spring和hibernate使用它)
AOP基本概念:
连接点(Joinpoint)
在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。 在Spring AOP中,一个连接点 总是 代表一个方法的执行。
切入点(Pointcut)
匹配连接点(Joinpoint)的断言。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时)。切入点表达式如何和连接点匹配是AOP的核心:Spring缺省使用AspectJ切入点语法。
通知(Advice)
在切面的某个特定的连接点(Joinpoint)上执行的动作。通知有各种类型,其中包括“around”、“before”和“after”等通知。
切面(Aspect)
一个关注点的模块化,这个关注点可能会横切多个对象。包含了:连接点、切入点、通知。可以通过@Aspect定义为一个类
目标对象(Target Object)
被一个或者多个切面(aspect)所通知(advise)的对象。也有人把它叫做被通知(advised) 对象。
织入(Weaving)
把切面(aspect)连接到其它的应用程序类型或者对象上,并创建一个被通知(advised)的对象。
通知的类型
前置通知(Before advice)
在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。
返回后通知(After returning advice)
在某连接点(join point)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
抛出异常后通知(After throwing advice)
在方法抛出异常退出时执行的通知。
后通知(After (finally)advice)
当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
环绕通知(Around Advice)
包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型。 环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。
spring中如何配置AOP
增加jar包,列表如下:
在spring中使用AOP需要在配置文件中增加如下内容:
<?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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <aop:aspectj-autoproxy /> <!– 支持AOP的注解方式--> </beans>
Annotation方式配置AOP
切面类声明
@Aspect
@Component //这个必须,告诉本类交给spring初始化
}切入点声明
}切入点语法示例和细节:
*代替任意多个任意字符。 ..表示任意个参数。 !表示非
}各种通知类型的定义
package com.sxt.interceptor; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; 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; import com.sxt.bean.User; /** * 日志拦截器 */ @Aspect @Component public class TestInterceptor { @Pointcut("execution(public * com.sxt.test.*.test*(..))") //声明一个名字为log的切入点 private void log(){ } @Before("log()"+"&&args(user)") //使用pointcut-->log .前置通知.处理传入的参数跟下面的形参保持一致即可。 private void before(User user){ System.out.println("方法执行前:"+user.getUname()); user.setUname("lisi"); System.out.println("方法执行前!"); } @After("log()") //最终后置通知。不管有无异常,最终都会执行! private void after(){ System.out.println("方法执行后!"); } @AfterReturning("log()") //方法正常结束,后置通知 private void afterReturning(){ System.out.println("方法执行后!after returning!"); } @AfterThrowing("log()") //抛出异常会执行,异常通知 private void afterThrowing(){ System.out.println("方法执行后!after throwing!"); } @Around("log()") //环绕通知在一个方法执行之前和之后执行 private Object around(ProceedingJoinPoint pjp){ System.out.println("环绕通知,方法执行前!"); Object obj = null; try { obj = pjp.proceed(); } catch (Throwable e) { e.printStackTrace(); } System.out.println("环绕通知,方法执行后!"); return obj; } }
XML方式配置AOP
<?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-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd "> <bean id="testInterceptor" class="com.sxt.interceptor.TestInterceptor"></bean> <bean id="userDao" class="com.sxt.test.UserDao"></bean> <aop:config> <aop:pointcut expression="execution(public !java.lang.String com.sxt.test.*.test*(com.sxt.bean.User,..))" id="log"/> <aop:aspect id="logAspect" ref="testInterceptor"> <aop:before method="before" arg-names="n" pointcut="execution(public !java.lang.String com.sxt.test.*.test*(com.sxt.bean.User,..)) and args(n)" /> <aop:after method="after" pointcut-ref="log" /> </aop:aspect> </aop:config> </beans>
事务以及项目应用
<?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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd "> <!-- mybatis 配置 --> <bean id="myBatisDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${db.driver}" /> <property name="jdbcUrl" value="${db.url}" /> <property name="user" value="${db.user}" /> <property name="password" value="${db.password}" /> <property name="minPoolSize" value="${c3p0.minPoolSize}" /> <property name="maxPoolSize" value="${c3p0.maxPoolSize}" /> <property name="maxIdleTime" value="${c3p0.timeout}" /> <!-- 当连接池耗尽时候,一次获得连接数 --> <property name="acquireIncrement" value="${c3p0.acquireIncrement}" /> <property name="maxStatements" value="${c3p0.max_statements}" /> <!-- 当连接池连接耗尽时,客户端getConnection(),所等待的时间 --> <property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}" /> <!-- 当连接失效时,获得连接的次数,0为无限次(重连) --> <property name="acquireRetryAttempts" value="${c3p0.acquireRetryAttempts}" /> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="myBatisDataSource" /> <property name="configLocation" value="classpath:config/mybatis-configuration.xml" /> <!-- <property name="transactionFactory"> <bean class="org.apache.ibatis.transaction.managed.ManagedTransactionFactory" /> </property>--> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.crs.**.mapper" /> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="myBatisDataSource" /> </bean> <tx:advice id="userTxAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="del*" propagation="REQUIRED" /> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="find*" propagation="REQUIRED" /> <tx:method name="query*" propagation="REQUIRED" /> <tx:method name="get*" propagation="REQUIRED" /> <tx:method name="select*" propagation="REQUIRED" /> <tx:method name="list*" propagation="REQUIRED" /> <tx:method name="*" propagation="REQUIRED" /> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="pc" expression="execution(* com.crs..service..*.*(..)))" /> <aop:advisor pointcut-ref="pc" advice-ref="userTxAdvice" /> </aop:config> </beans>