1. 认识Spring
1.1 企业级应用:
指为商业组织、大型企业创建并部署的解决方案及应用。这些大型企业级应用的结构复杂,涉及的外部资源众多,事务米家、数据规模大、用户数量多,有较强的安全性考虑和较高的性能要求。
Spring致力于Java EE应用的各种解决方案,而不仅仅专注于某一层的方案。可以说,Spring是企业应用开发的“一站式”选择,贯穿表现层、业务层和持久层。并且Spring并不是取代那些已有的框架,而是以高度的开放性与他们无缝整合。
1.2 Spring整体架构
Spring是一个轻量级框架,他大大简化了Java企业级开发,提供强大、稳定功能的同事并没有带来额外的负担。Spring有两个主要目标:一是让现有技术更易于使用,而是养成良好的编程习惯(或者称为最佳实践)。
作为一个全面的解决方案,Spring坚持一个原则:不重新发明轮子。已经有较好解决方案的领域,Spring绝不做重复性的实现。
Spring框架有大约20个功能模块组成。这些模块被分成六个部分,分别是Core Container、Data Access/Integration、Web、AOP(Aspect Object Programming)、Instrumentation及Test
Spring体系结构
Spring Core是框架的最基础部分,提供了IOC特性。
Spring Context为企业级开发提供了遍历的集成工具。
Spring AOP 是基于Spring COre 的符合规范的面向切面编程的实现。
Spring JDBC 提供了JDBC的抽象层,简化了JDBC编码,同事是代码更健壮。
Spring ORM对市面上流行的ORM框架提供了支持。
Spring Web为Spring在Web应用程序中的使用提供了支持。
2. Spring IoC的简单运用
2.1 IoC/DI
控制反转(Inversion of Control,IoC)也称为依赖注入(Dependency Injection,DI),是面向对象编程中的一种涉及理念,用来降低程序代码之间的耦合度
依赖一般指通过局部变量、方法参数、返回值等建立的对于其他对象的调用关系。
2.2 Spring实现输出
开发第一个Spring项目,输出“Hello,Spring!”
要求:
1.编写HelloSpring类输出“Hello,Spring!”
2.其中的字符串内容“Spring”是通过Spring框架赋值的HelloSpring类中的。
实现步骤
(1)下载Spring并添加到项目中。
HelloSpring需要的jar文件
(2)编写Spring配置文件
<?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-3.2.xsd
<!--通过Bean元素声明需要Spring创建的实例,该实例的类型通过class属性指定,
并通过id属性为该实例指定一个名称,以便于访问-->
<bean id="helloSpring" class="cn.springdemo.HelloSpring">
<!-- property元素用来为实例的属性赋值,
此处实际是调用setWho()方法是此案赋值操作 -->
<property name="who">
<!--此处将字符串“Spring”赋值个who属性-->
<value>Spring</value>
</property>
</bean>
</beans>
在Spring配置文件中,使用<bean>元素来定义Bean(也可称为组件)的实例。
<bean>元素有个两个常用属性:
id:表示定义的Bean实例的名称
class:表示定义的Bean实例的类型
(3)编写代码通过Spring获取HelloSpring实例
HelloSpring.java
/**
* 第一个Spring,输出"Hello,Spring"
* @author lenovo
*
*/
public class HelloSpring {
//定义who属性,该属性的值将通过Spring框架进行设置
private String who = null;
public void print(){
System.out.println("Hello," + this.getWho() + "!");
}
public String getWho() {
return who;
}
public void setWho(String who) {
this.who = who;
}
}
测试代码
//通过ClassPathXmlApplicationContext实例化Spring的上下文
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//通过ApplicationContext的getBean()方法,根据id来获取Bean的实例
HelloSpring helloSpring = (HelloSpring)context.getBean("helloSpring");
//执行print()方法
helloSpring.print();
ApplicationContext是一个接口,负责读取Spring配置文件,管理对象的价值、生成,维护Bean对象之间的依赖关系,负责Bean的生命周期等。
ClassPathXmlApplicationContext是ApplicationContext接口的实现类,用于从classpath路径中读取Spring配置文件
相对于“控制反转”,“依赖注入”的说法也许更容易理解一些,即有容器(如Spring)负责把组件所“依赖”的具体对象“注入”(赋值)个组件,从而避免组件之间以硬编码的方式耦合在一起。
3. Spring AOP的简单运用
3.1 认识AOP
面向切面编程(Aspect Oriented Programming,AOP)是软件编程思想发展到一定阶段的产物,是对面向对象编程(Object Oriented Programming,OOP)的友谊补充。AOP一般适用于具有横切逻辑的场合,如访问控制、事务管理、性能监测等。
什么是横切逻辑?
在业务系统中,总有一些散落、渗透到系统各处且不得不处理的事情,这些穿插在既定业务中的操作及时所谓的“横切逻辑”,也称为切面。
面向切面编程,简单地说就是在不改变原有程序的基础上为代码段增加新的功能,对其进行增强处理。他的设计思想来源于代理设计模式。
通常情况下调用对象的方法
通过代理对象调用方法
在代理模式中可以为对象设置一个代理对象,代理对象为fun()提供一个代理方法,嗲通过代理对象的fun()方法调用原对象的fun()方法时,就可以在代理方法中添加新的功能,这既是所谓的增强处理。
面向切面编程的基本概念
- 切面(Aspect):一个模块或的横切逻辑(或称横切关注点),可以会横切多个对象。
- 连接点(Join Point):程序执行中的某个具体的执行点。
- 增强处理(Advice ):切面在某个特定连接点上执行的代码逻辑。
- 切入点(Pointcut):对连接点的特征进行描述,可以使用正则表达式。增强处理和一个切入点表达式相关联,并在与这个切入点匹配的某个连接点上运行。
- 目标对象(Target object):被一个或多个切面增强的对象。
- AOP代理(AOP proxy):有AOP框架所创建的对象,实现执行增强处理方法等功能。
- 织入(Weaving):将增强处理连接到应用程序中的类型或对象上的过程。
- 增强处理类型:前置增强、后置增强、环绕增强、异常抛出增强、最终增强
说明:
切面可以理解为有增强处理和切入点组成,既包含了横切逻辑的定义,也包含了连接点的定义。面向切面编程主要关心两个问题,即在什么位置执行什么功能,SpringAOP是负责实施切面的框架,即由SpringAOP完成织入工作
3.2 Spring AOP初体验
实现思路及关键代码
(1)在项目中添加Spring AOP 相关的jar文件。
(2)编写前置增强和后置增强实现日志功能。
编写业务类UserServiceImpl
/**
*
* <p>Title: UserServiceImpl</p>
* <p>Description: 用户业务类,实现对User功能的业务管理</p>
* <p>Company: www.bdqn.cn</p>
* @author shuai
* @date 10:53:15 AM
*/
public class UserServiceImpl implements UserService {
//声明接口类型的引用和具体实现类解耦合
private UserDao dao;
//dao属性的setter访问器
public void setDao(UserDao dao) {
this.dao = dao;
}
public void addNewUser(User user) {
//调用用户Dao的方法来保持用户信息
dao.save(user);
}
}
编写增强类
import java.util.Arrays;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
/**
* 定义包含增强方法的JavaBean
* @author lenovo
*
*/
public class UserServiceLogger {
private static final Logger LOGGER = Logger.getLogger(UserServiceLogger.class);
public void pointcut(){}
//代表前置增强的方法
@Before("pointcut()")
public void before(JoinPoint jp){
LOGGER.info("调用" + jp.getTarget() + "的" + jp.getSignature().
getName() + "方法。方法入参:" + Arrays.toString(jp.getArgs()));
}
//代表后置增强的方法
@AfterReturning(pointcut="pointcut()",returning="returnValue")
public void afterReturning(JoinPoint jp,Object returnValue){
LOGGER.info("调用" + jp.getTarget() + "的" + jp.getSignature().
getName() +"方法。方法返回值:" + returnValue);
}
}
(3)编写Spring配置文件,对业务方法进行增强处理。
对相关组件进行声明
<bean id="dao" class="cn.dao.impl.UserDaoImpl"></bean>
<bean id="service" class="cn.service.impl.UserServiceImpl">
<property name="dao" ref="dao"></property>
</bean>
<bean id="theLogger" class="cn.aop.UserServiceLogger"></bean>
在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-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
<aop:config>
<aop:pointcut id="pointcut" expression="execution(public void addNewUser(cn.pojo.User))"/>
<!-- 引用包含增强方法的Bean -->
<aop:aspect ref="theLogger">
<!-- 将before()方法定义为前置增强并引用pointcut切入点 -->
<aop:before method="before" pointcut-ref="pointcut" />
<!-- 将afterReturning()方法定义为后置增强并引用pointcut切入点 -->
<!-- 通过returning属性指定为名为result的参数注入返回值 -->
<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result" />
</aop:aspect>
</aop:config>
</beans>
(4)编写代码,获取带有增强处理的业务对象。
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService service = (UserService)context.getBean("service");
User user = new User();
user.setId(1);
user.setUserName("test");
user.setUserPassword("123456");
user.setEmail("test@xxx.com");
service.addNewUser(user);
输出结果