spring框架的学习笔记,以及演示代码。
Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。其目的为:解决企业应用开发的复杂性。功能为:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能。任何Java应用都可以使用。总的来说:Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。
1、非侵入式设计
Spring是一种非侵入式(non-invasive)框架,它可以使应用程序代码对框架的依赖最小化。
2、方便解耦、简化开发
Spring就是一个大工厂(底层为map容器),可以将所有对象的创建和依赖关系的维护工作都交给Spring容器的管理,大大的降低了组件之间的耦合性。
3、支持AOP(面向切面编程)
Spring提供了对AOP的支持,它允许将一些通用任务,如安全、事物、日志等进行集中式处理,从而提高了程序的复用性。
4、支持声明式事务处理
只需要通过配置就可以完成对事物的管理,而无须手动编程。
5、方便程序的测试
Spring提供了对Junit4的支持,可以通过注解方便的测试Spring程序。
6、方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如Struts、Hibernate、MyBatis、Quartz等)的直接支持。
7、降低Jave EE API的使用难度。
Spring对Java EE开发中非常难用的一些API(如JDBC、JavaMail等),都提供了封装,使这些API应用难度大大降低。
Test:Spring的单元测试模块、整Junit
需要导入的包
spring-test-4.0.0.RELEASE
Core Container:核心容器(IOC)
需要导入的包
spring-beans-4.0.0.RELEASE、
spring-core-4.0.0.RELEASE、
spring-context-4.0.0.RELEASE、
spring-expression-4.0.0.RELEASE
AOP+Aspects(面向切面编程模块)
spring-aop-4.0.0.RELEASE、spring-aop-4.0.0.RELEASE
Data Access:spring访问数据库模块(数据库访问、事务管理、整合hibernate)
spring-jdbc-4.0.0.RELEASE、spring-orm(Object Relation Mapping)-4.0.0.RELEASE、
spring-ox(xml)m-4.0.0.RELEASE、spring-jms-4.0.0.RELEASE、(Intergration)
spring-tx-4.0.0.RELEASE(事务)
Web:Spring开发web应用模块
spring-websocket(新的技术)-4.0.0.RELEASE、
spring-web-4.0.0.RELEASE、和原生的web相关(servlet)
spring-webmvc-4.0.0.RELEASE、开发web项目的(web)
spring-webmvc-portlet-4.0.0.RELEASE(开发web应用的组件集成)
IoC(Inversion Of Control)即控制反转,其具体就是由容器来控制业务对象之间的依赖关系,而不是像传统方式中由代码来直接控制。控制反转的本质,是控制权由应用代码转到了外部容器,控制权的转移即是所谓的反转。控制权的转移带来的好处就是降低了业务对象之间的依赖程度,即实现了解耦。
第一个为字节码包,.javadoc为文档包,.source为源码包
spring-beans-4.0.0.RELEASE
spring-core-4.0.0.RELEASE
spring-context-4.0.0.RELEASE
spring-expression-4.0.0.RELEASE
commons-logging-1.1.3.jar(依赖包)
<!--创建一个Spring Bean Configuration File(Spring的bean配置文件)-->
<!-- 注册一个Person对象,Spring会自动创建这个Person对象 -->
<!--
一个Bean标签可以注册一个组件(对象、类)
class:写要注册的组件的全类名
id:这个对象的唯一标示;
-->
<bean id="person" class="com.atguigu.bean.Person">
<!--
使用property标签为Person对象的属性赋值
name="lastName":指定属性名
value="张三":为这个属性赋值
-->
<property name="lastName" value="张三"></property>
<property name="age" value="18"></property>
<property name="email" value="zhangsan@spring.com"></property>
<property name="gender" value="男"></property>
</bean>
@Test //代码测试注解
public void test() {
//ApplicationContext:代表ioc容器
//ClassPathXmlApplicationContext:当前应用的xml配置文件在 ClassPath下
//根据spring的配置文件得到ioc容器对象
ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc.xml");
//容器帮我们创建好对象了;
Person bean = (Person) ioc.getBean("person");
System.out.println(bean);
}
基于注解的IOC配置,与在xml中配置目的是一样的,都是降低代码之间的耦合度的,只是配置的形式不一样
和前面基于配置的IOC一样。
<!-- 将com.xhq包下的添加了注解的类添加到容器中 -->
<context:component-scan base-package="com.xhq"/>
直接在类上添加注解即可,value中的值相当于配置bean中的id
@Component(value="Person01")
public class Person {
}
其余注解的作用:
3.2.1 @Component
3.2.2 @Controller
一般用于表现层的注解。用法与@Component相同
3.2.3 @Service
一般用于业务层的注解。用法与@Component相同
3.2.4 @Repository
一般用于持久层的注解。 用法与@Component相同
在要new的变量前加上@Autowired注解即可
Person person01 = new Person();
@Autowired
Person person02;
两种方法都是创建一个对象,只不过第二种使用自动装配,将对象存入容器中,方便管理。
其余注解的作用:
3.3.1 @Autowired
3.3.2 @Qualifier
作用: 在自动按照类型注入的基础之上,再按照Bean的id注入。它在给字段注入时不能独立使用,必须和@Autowire一起使用;但是给方法参数注入时,可以独立使用。
属性: value:指定bean的id。
3.3.3 @Resource
作用: 直接按照Bean的id注入。它也只能注入其他bean类型。
属性: name:指定bean的id。
3.3.4 @Value
作用:注入基本数据类型和String类型数据的
属性:value:用于指定值
4.1、ApplicationContext(IOC容器的接口)
4.2、容器中对象的创建在容器创建完成的时候就已经创建好了
4.3、同一个组件在ioc容器中是单实例的;容器启动完成都已经创建准备好的
4.4、容器中如果没有这个组件,再去获取组件,会报异常
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No bean named 'person' is defined
4.5、ioc容器在创建这个组件对象的时候,(property)会利用setter方法为javaBean的属性进行赋值
4.6、javaBean的属性名是由什么决定的?getter/setter方法就是属性名,set去掉后面那一串首字母小写就是属性名
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
在程序运行期间,将某段代码动态的切入到指定方法的指定位置进行运行的这种编程方式叫做面向切面编程。
日志记录,性能统计,安全控制,事务处理,异常处理等等。
将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
以为Calculator添加log日志为例:
很多人在初次接触 AOP 的时候可能会说,AOP 能做到的,一个定义良好的 OOP 的接口也一样能够做到,我想这个观点是值得商榷的。AOP和定义良好的 OOP 的接口可以说都是用来解决并且实现需求中的横切问题的方法。但是对于 OOP 中的接口来说,它仍然需要我们在相应的模块中去调用该接口中相关的方法,这是 OOP 所无法避免的,并且一旦接口不得不进行修改的时候,所有事情会变得一团糟;AOP 则不会这样,你只需要修改相应的 Aspect,再重新编织(weave)即可。 当然,AOP 也绝对不会代替 OOP。核心的需求仍然会由 OOP 来加以实现,而 AOP 将会和 OOP 整合起来,以此之长,补彼之短。
//帮Calculator生成代理对象的类
public class CalculatorProxy {
//为传入的参数对象创建一个动态代理对象
public static Calculator getProxy(final Calculator calculator) {
//方法执行器,帮我们目标对象执行目标方法
InvocationHandler h = new InvocationHandler() {
/**
* Object proxy:代理对象;给jdk使用,任何时候都不要动这个对象
* Method method:当前将要执行的目标对象的方法
* Object[] args:这个方法调用时外界传入的参数值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
try {
LogUtils.logStart(method, args); //方法执行之前
// 利用反射执行目标方法
//目标方法执行后的返回值
result = method.invoke(calculator, args); //方法执行
LogUtils.logReturn(method, result); //方法正常返回
} catch (Exception e) {
LogUtils.logException(method,e); //方法异常
}finally{
LogUtils.logEnd(method); //方法结束
}
//返回值必须返回出去外界才能拿到真正执行后的返回值
return result;
}
};
Class<?>[] interfaces = calculator.getClass().getInterfaces();
ClassLoader loader = calculator.getClass().getClassLoader();
//Proxy为目标对象创建代理对象;
Object proxy = Proxy.newProxyInstance(loader, interfaces, h);
return (Calculator) proxy;
}
}
2.2.1、写起来难;
2.2.2、jdk默认的动态代理,如果目标对象没有实现任何接口,是无法为他创建代理对象的
3.1.1、导包
commons-logging-1.1.3.jar
spring-aop-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
Spring支持面向切面编程的包是:
spring-aspects-4.0.0.RELEASE.jar:基础版
加强版的面向切面编程(即使目标对象没有实现任何接口也能创建动态代理)
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
3.1.2、写配置
3.1.2.1
将目标类和切面类(封装了通知方法(在目标方法执行前后执行的方法))加入到ioc容器中
3.1.2.2
还应该告诉Spring到底哪个是切面类@Aspect
3.1.2.3
告诉Spring,切面类里面的每一个方法,都是何时何地运行;
@Before:在目标方法执行之前执行(前置通知)
@After:在目标方法执行之后执行(后置通知)
@AfterThrowing:在目标方法抛出异常以后执行(异常通知)
@AfterReturning:在目标方法正常返回之后执行(返回通知)
@Around:环绕通知
3.1.2.4
开启基于注解的AOP模式
3.1.3、测试
Calculator bean = ioc.getBean(Calculator.class);
bean.add(2, 1);
1)、实现简单
2)、而且没有强制要求目标对象必须实现接口