什么是Spring
- spring是一个轻量级的“一站式”的开源框架。spring框架涵盖了javaEE开发的所有的技术思想和设计原理。这些技术思想和原理并不是Spring创新的技术,只是把已经存在的技术思想重新整合成的一个新的框架。
- JavaEE官方平台的核心框架:EJB(Enterprise JavaBean)。重量级开发JavaEE应用的框架,相当于Spring+Hibernate技术组合,但是EJB可以做分布式开发。EJB应用只能部署在重量级的容器(服务器),例如,JBoss,
Weblogic , WebSphere, Spring应用可以部署在web容器中,例如:Tomcat.
Spring框架组成
-
核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC)
模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。 -
Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring
的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。 -
Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring
DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。 -
Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
-
Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web
模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。 -
Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
-
JDBC Template:对jdbc的高度封装。
Spring Core 核心模块
先了解两个重要的概念:
- IOC(Inverse Of Controll)控制反转:
传统的java实例的创建是由程序通过new关键字创建的,称为“硬编码”。控制反转指的是这种传统的创建对象的方式的“反转”,也就是由spring对象容器来创建。简单而言,就是容器托管对象。 - DI (Dependency Injection)依赖注入:
依赖,指的是对象与对象的某种关系。依赖关系的初始化不通过“硬编码”完成,而是“容器“进行初始化,也就是由容器注入该实例的引用。
伪代码:
class Human{
private Head head;
private Body body;
private Leg leg;
....
public void doSomething(Work work){
work.cal();
}
}
class Head{
}
class Body{
}
class Leg{
}
interface Work {
}
class UserService{
private UserDao userDao;
}
依赖注入的方式:
- setter注入 通过属性的setter方法完成初始化
- 构造器注入 通过构造函数
- 接口注入 例如:servlet的doGet()和doPost()方法 ,一般在框架或容器中使用较多
- 注解注入 整合时使用最方便(最常用)
spring基础的入门程序
- setter注入
<bean id="person" class="com.gec.spring.bean.Person">
<property name="name" value="李四"></property>
<property name="speaking" value="Good Afternoon"></property>
</bean>
- 构造器注入
<bean id="host" class="com.gec.spring.bean.Host"></bean>
<bean id="display" class="com.gec.spring.bean.Display"></bean>
<bean id="computer" class="com.gec.spring.bean.Computer">
<constructor-arg index="0" ref="host"></constructor-arg>
<constructor-arg index="1" ref="display"></constructor-arg>
</bean>
- P命名空间注入
<bean id="host" class="com.gec.spring.bean.Host"></bean>
<bean id="display" class="com.gec.spring.bean.Display"></bean>
<bean id="computer" class="com.gec.spring.bean.Computer" p:host-ref="host" p:display-ref="display"/>
- 特殊数据的注入,指的是集合的注入
<bean id="department" class="com.gec.spring.bean.Department">
<property name="name" value="财务部"></property>
<!-- List的注入 -->
<property name="empList">
<list>
<ref bean="emp1"/>
<ref bean="emp2"/>
</list>
</property>
<!-- Set的注入 -->
<property name="empSet">
<set>
<ref bean="emp1"/>
<ref bean="emp2"/>
</set>
</property>
<!-- Map类型的注入 -->
<property name="empMap">
<map>
<entry key="1" value-ref="emp1"></entry>
<entry key="2" value-ref="emp2"></entry>
</map>
</property>
<property name="pp">
<props>
<prop key="pp1">emp1</prop>
<prop key="pp2">emp2</prop>
</props>
</property>
</bean>
<bean id="emp1" class="com.gec.spring.bean.Employee" p:name="张三" p:id="1"></bean>
<bean id="emp2" class="com.gec.spring.bean.Employee" p:name="李四" p:id="2"></bean>
- 自动装配
spring管理Bean的作用域:
- 单例 singleton (默认)
<bean id="date1" class="java.util.Date" scope="singleton"></bean>
- 原型(多例) prototype
以下三种在javaweb应用中使用
- request
- session
- Global Session
Spring 的 AOP编程
- AOP Aspect Oriented Programming 面向切面编程, “拦截器”。
- 在JavaEE技术体系中,拦截技术相当重要。主要的作用是降低组件间的“耦合度”。
javaweb 过滤器 过滤一切可访问的资源(拦截http请求的),包括,jsp,servlet,css,js,…
struts2 springmvc 包含系统的拦截器和自定义拦截器 拦截控制器
spring AOP编程 拦截业务层的方法。 - AOP编程和OOP编程的共同点:都是解决应用的共性问题,如果在应用中找不到继承关系,可以使用AOP来解决通用性问题。 spring
aop 中拦截的方式(方法的增强), 粒度很细:
public void dosomething(){
try{
//1.前置增强
//3. 环绕增强(前置)
service(); //核心的业务
//3. 环绕增强(后置)
//2. 后置增强
}catch(){
//4.异常增强
}finally{
//5. 最终增强
}
}
- AOP的术语:
– aspect 切面 相当于拦截器类,解决通用性问题
– pointcut 切入点 哪些类的哪些方法要被拦截
– weaver 织入 对被拦截的目标对象的进一步封装 - AOP编程的实现方式
– 实现接口的方式 , 在低版本的spring中常用 ,每种增强都会对应有一个接口。
– schema的方式, 直接使用xml文档配置各种增强方式
(1)切面类
package com.gec.spring.aop;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
/**
* aspect : 切面类 ,解决通用性问题
* @author gec
*
*/
public class MyAOP {
//前置增强
public void before(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs(); //获取拦截方法的参数列表
String methodName = joinPoint.getSignature().getName(); //补拦截方法的名称
Object target = joinPoint.getTarget(); //被拦截的目标实例(业务类的实例)
System.out.println("前置 方法名:" + methodName+",参数列表:"+Arrays.toString(args)+",目标对象:"+target);
}
//后置增强: 带返回值参数
public void afterReturning(JoinPoint joinPoint,Object returnValue) {
Object[] args = joinPoint.getArgs(); //获取拦截方法的参数列表
String methodName = joinPoint.getSignature().getName(); //补拦截方法的名称
Object target = joinPoint.getTarget(); //被拦截的目标实例(业务类的实例)
System.out.println("后置 方法名:" + methodName+",参数列表:"+Arrays.toString(args)+",目标对象:"+target+",返回值:"+returnValue);
}
//环绕增强
public Object arround(ProceedingJoinPoint pjp) throws Throwable{
Object[] args = pjp.getArgs(); //获取拦截方法的参数列表
String methodName = pjp.getSignature().getName(); //补拦截方法的名称
Object target = pjp.getTarget(); //被拦截的目标实例(业务类的实例)
System.out.println("环绕(前置)方法名:" + methodName+",参数列表:"+Arrays.toString(args)+",目标对象:"+target);
//核心业务方法的调用
Object returnValue = pjp.proceed();
System.out.println("环绕(后置) 方法名:" + methodName+",参数列表:"+Arrays.toString(args)+",目标对象:"+target+",返回值:"+returnValue);
return returnValue;
}
}
(2)schema配置
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<bean id="userService" class="com.gec.spring.service.impl.UserServiceImpl"></bean>
<bean id="myAop" class="com.gec.spring.aop.MyAOP"></bean>
<!-- aop的织入weaver -->
<aop:config>
<aop:pointcut id="pointcut" expression="execution(public * com.gec.spring.service.impl.*.*(..))"/>
<aop:aspect ref="myAop">
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="returnValue"/>
<aop:around method="arround" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
</beans>
– 注解的方式, 使用注解说明增强方式
(1) 切面类
package com.gec.spring.aop;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class MyInterceptor {
//1. 前置增强
@Before("execution(public * com.gec.spring.service.impl.*.*(..))")
public void before(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs(); //被拦截方法的参数列表
String methodName = joinPoint.getSignature().getName(); // 被拦截方法名
Object obj = joinPoint.getTarget(); //被拦截的目标对象,被代理对象
System.out.println("前置 方法名:" + methodName + ", 参数列表:" + Arrays.toString(args)+",拦截的目标对象:"+obj);
}
//2. 后置通知
@AfterReturning(pointcut="execution(public * com.gec.spring.service.impl.*.*(..))",returning="returnValue")
public void afterReturning(JoinPoint joinPoint,Object returnValue) {
Object[] args = joinPoint.getArgs(); //被拦截方法的参数列表
String methodName = joinPoint.getSignature().getName(); // 被拦截方法名
Object obj = joinPoint.getTarget(); //被拦截的目标对象,被代理对象
System.out.println("后置 方法名:" + methodName + ", 参数列表:" + Arrays.toString(args)+",拦截的目标对象:"+obj + ",返回值:"+returnValue);
}
//环绕增强
@Around("execution(public * com.gec.spring.service.impl.*.*(..))")
public Object arround(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs(); //被拦截方法的参数列表
String methodName = pjp.getSignature().getName(); // 被拦截方法名
Object obj = pjp.getTarget(); //被拦截的目标对象,被代理对象
System.out.println("环绕-前置 方法名:" + methodName + ", 参数列表:" + Arrays.toString(args)+",拦截的目标对象:"+obj);
//业务方法的调用
Object returnValue = pjp.proceed();
System.out.println("环绕-后置 返回值 :" + returnValue);
return returnValue;
}
}
(2) spring的核心xml文件中启动注解
<bean id="myInterceptor" class="com.gec.spring.aop.MyInterceptor"></bean>
<!-- 启动aop注解配置 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
Aop编程的应用
AOP的设计模式- 代理设计模式
代理模式:对代理目标的功能增强,也就是“拦截”。
1.静态代理
组成 :
- 抽象主题
- 真实主题
- 代理类
2.动态代理
动态代理类的实现
package com.gec.spring.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理类
*
* @author gec
*
*/
public class DynaProxyBean implements InvocationHandler {
// 代理的目标对象,业务类的实例
private Object proxyObj;
private DynaProxyBean(Object proxyObj) {
this.proxyObj = proxyObj;
}
/**
* 产生代理对象的工厂方法
*
* @param obj
* 被代理目标对象
* @return
*/
public static Object proxy(Object obj) {
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
.getClass().getInterfaces(), new DynaProxyBean(obj));
}
@Override //增强 Method表示被代理目标对象的核心方法
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
preRequest();
Object returnValue = method.invoke(this.proxyObj, args);
return returnValue;
}
private void preRequest() {
System.out.println("前置增强");
}
}