企业级系统
大规模:用户数量多、数据规模大、功能众多
性能和安全要求高
业务复杂
灵活应变
Spring轻量级框架、JavaEE的春天,当前主流框架
一站式的企业应用开发框架
目标
使现有技术更加易用,推进编码最佳实践
内容
IoC容器
AOP实现
数据访问支持
简化JDBC/ORM框架
声明式事务
Web集成
Spring体系结构
Data Access/Integration
JDBC/ORM/OXM/JMS/Transactions
Web(MBC/Remoting)
Web/Servlet/Portlet/Struts
AOP
Aspects
Instrumentation
Core Container (Spring核心,Beans/Core/Context核心的核心
Beans/Core/Context/Expression Language
Test
Spring设计理念
Spring是面向Bean的编程
Spring两大技术
控制反转(IoC:Inversion of Control)/依赖注入(DI:Dependency Injection)
面向切面编程(AOP:Aspect Oriented Programming)
Beans:JavaBean 实体类
Core:util工具类
Context: 编程环境配置
Spring的优点
低侵入式设计
独立于各种应用服务器
依赖注入特性将组件关系透明化,降低了耦合度
面向切面编程特性允许将通用任务进行集中式处理
与第三方框架的良好整合
Spring弥补了EJB框架的不足,是J2EE的春天
Spring是面向bean的编程
Spring的两大核心技术
IoC定义和原理(控制反转)
将组件对象的控制权从代码本身转移到外部容器
组件化的思想:分离关注点,使用接口,不再关注实现
依赖的注入:将组件的构建和使用分开
【在A类中调用B类,在A类中new一个B类的对象】将B类放在一个容器中,不用再A类中new一个。提供一个工厂(工厂中有多个类),如果A类需要某个类的实例,可以通过工厂来实现这个类的实例。跟MyBatis中的数据库工厂一样,可以创建多个SqlSession
工厂模式:根据我们提供的我们所需的对象实例的描述,为我们返回所需要的产品
1、产品的规范 定义接口 实体类实现的方法
2、产品 实体类,实现接口
3、工厂 将实体类封装在工厂中
4、客户端/调用
如何使用Spring实现控制反转
编写HelloSpring类,输出“Hello,Spring!”
字符串“Spring”通过Spring注入到HelloSpring类中
步骤:
1、添加Spring.jar到项目中
2、编写配置文件
编写代码获取HelloSpring实例
Spring官网:repo.spring.io
使用Spring IoC步骤
1、导入spring jar包
commons-logging-1.1.1.jar
log4j-1.2.17.jar
spring-beans-3.2.13.RELEASE.jar
spring-context-3.2.13.RELEASE.jar
spring-core-3.2.13.RELEASE.jar
spring-expression-3.2.13.RELEASE.jar
2、创建spring 管理的类这里是HelloSpring
package cn.spring.demo;
public class HelloSpring {
//定义变量who,它的值通过spring框架进行注入
private String who;
//定义打印方法,输出一句完整的问候
public void print(){
System.out.println("Hello,"+this.getWho()+"!");
}
public String getWho() {
return who;
}
public void setWho(String who) {
this.who = who;
}
}
3、新建配置文件ApplicationContext.xml
配置ApplicationContext.xml文件
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.xsd">
Spring
4、创建测试类
//利用ClassPathXmlApplicationContext获取spring配置文件
//也可以用FileSystemXmlApplicationContext读取配置文件
ApplicationContext context =
new ClassPathXmlApplicationContext("ApplicationContext.xml");
//获取配置文件中的bean
HelloSpring helloSpring = (HelloSpring)context.getBean("helloSpring");
helloSpring.print();
设置注入
使用元素定义一个组件
id属性:指定一个用来访问的唯一名称
name属性:指定多个别名,名字之间使用逗号、分号或空格进行分割
如何开发一个打印机
可灵活配置使用彩色墨盒或灰色墨盒
可灵活配置打印页面的大小
打印功能的实现依赖于墨盒和纸张
步骤
定义墨盒和纸张的接口标准
使用接口标准开发打印机
组装打印机
运行打印机
不要忘记为被注入的属性提供setter方法
AOP定义和原理
【平常一段代码有 记录日志代码,业务代码,事务控制代码,】
(我们构建系统的目的是解决业务问题,现在却要维护多个方面的事情,不能做到专一)
横切逻辑,
业务代码
AOP的目标;让我们可以“专心做事”
AOP原理
将复杂的需求分解出不同的方面,将功能集中解决
采用代理机制组装起来运行,在不改变原程序的基础上对代码进行增强处理,增加新的功能
代理对象fun(),通过代理对象来调用原对象的方法;代理对象方法前后都可插入代码,这些代码就是增强处理
所谓面向切面编程,是一种通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序添加功能的技术
AOP相关术语
1、增强处理(Advice)
前置增强
后置增强
环绕增强,异常抛出增强、最终增强等类型
【代理类】
+fun1() :void
+addNewUser :boolean
+fun2(): void
2、切入点(Pointcut)是系统要增强处理的点,就是连接点的查询条件
3、连接点(Join Point)
4、切面(Aspect)
5、目标对象(Target object)被增强的类
6、AOP代理(AOP proxy)代理类
7、织入(Weaving)将切入点插入增强处理
AOP实现自动的系统日志功能
使用Spring AOP实现日志输出
在业务方法执行前后成功添加了日志功能
实现步骤
1、在项目添加Spring AOP的jar文件
commons-logging-1.1.1.jar
log4j-1.2.17.jar
spring-beans-3.2.13.RELEASE.jar
spring-context-3.2.13.RELEASE.jar
spring-core-3.2.13.RELEASE.jar
spring-expression-3.2.13.RELEASE.jar
aopalliance-1.0.jar
aspectjweaver-1.6.9.jar
spring-aop-3.2.13.RELEASE.jar
2、编写前置增强和后置增强实现日志功能(编写处理类)
3、编写Spring配置文件,对业务方法进行增强处理
4、编写代码获取带有增强处理的业务对象
Spring中IoC机制是在配置文件中就可以进行参数的传递,无需在外面传参。特别是参数是实体类的,可以直接在配置文件中引用,不需要外面创建一个类,再调用。
public class User {
private Child child;
public void add(){
child.get();
}
public void setChild(Child child){
this.child = child;
}
/*public void add(Child child){
child.get();
}*/
}
public void add(Child child){
child.get();
}本来需要用这个将对象传到User类进去的,
Child child = new Child();
User user = new User();
user.add(child);
现在通过配置文件直接调用Child类,无需new一个类
name="child"是上面方法public void setChild(Child child)中的setChild的Child
ref="_child"将类引用到User类中,通过setChild方法得到该类
public class Child {
public void get(){
System.out.println("hello");
}
}
@Test
public void testUser() {
//利用ClassPathXmlApplicationContext获取spring配置文件
//也可以用FileSystemXmlApplicationContext读取配置文件
ApplicationContext context =
new ClassPathXmlApplicationContext("ApplicationContext.xml");
//利用context对象中的getBean()方法获得里面配置的类
User user = (User) context.getBean("user");
user.add();
}
在Spring配置文件中通过元素为构造方法传参
注意:一个constructor-arg元素表示构造方法的一个参数,且使用时不区分顺序。
2、通过constructor-arg元素的Index属性可以指定该参数的位置索引,位置从0开始
3、constructor-arg元素还提供了type属性用来指定参数的类型,避免字符串和基本数据类型的混淆
hello
world
设置注入:
通过setter访问器实现
灵活性好,但setter方法数量较多
时效性差
通过无参构造实例化
构造注入:
通过构造方法实现
灵活性差、仅靠重载限制太多
时效性好
通过匹配构造方法实例化,但建议保留无参构造方法
p命名空间的特点:使用属性而不是子元素的形式配置Bea的属性,从而简化配置代码
对于直接量(基本数据类型、字符串)属性:p:属性名=“属性值”
对于引用Bean的属性:p:属性名-ref="Bean的id"
使用前要先要在Spring配置文件中引入p命名空间
xmlns:p="http://www.springframework.org/schema/p"
使用p命名空间注入属性值
注入不同数据类型
1、注入直接量
使用标签实现
注意特殊字符的处理
2、引用Bean
使用标签实现
注意bean属性和local属性的区别【当项目很大时,会有多个配置文件,local表示本文件】
3、使用内部Bean
4、注入集合类型的属性
分别使用
///
标签实现
5、注入null和空字符串值
使用 注入Null值
使用注入空字符串值
P&G
足球
篮球
足球
篮球
足球
篮球
football
足球
basketball
篮球
足球
篮球
异常抛出增强的特点
1、在目标方法抛出异常时织入增强处理
2、可拔插的异常处理方案
元素:定义异常抛出增强
ponitcut-ref="pointcat" throwing="e" />
method="afterThrowing" 是AOPException类中的方法名
public class AOPException {
public void afterThrowing(JoinPoint jp,RuntimeException e){
System.out.println(jp.getSignature().getName()+":"+e.getMessage());
}
}
最终增强的特点
1、无论方法是否抛出异常,都会在目标方法最后织入增强处理,即:该增强都会得到执行
2、类似异常处理机制中finally块的作用,一般用于释放资源
3、可以为各功能模块提供统一的,可拔插的处理方案
元素:定义最终增强
最终增强处理类
public class AOPAfter {
public void after(JoinPoint jp){
System.out.println(jp.getSignature().getName()+"方法结束了");
}
}
环绕增强的特点
1、目标方法前后都可织入增强处理
2、功能最强大的增强处理
3、可获取或修改目标方法的参数、返回值,可对它进行异常处理,甚至可以决定目标方法是否执行
元素:定义环绕增强
增强处理类
public class AOPAround {
public Object around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("调用"+pjp.getTarget()+"的"
+pjp.getSignature()+"目标方法.方法参数"+Arrays.toString(pjp.getArgs()));
Object result;
try{
result = pjp.proceed();
System.out.println("调用"+pjp.getTarget()+"的"
+pjp.getSignature()+"目标方法.方法返回值"+result);
return result;
}
catch(Throwable e)
{
System.out.println(pjp.getSignature().getName()+"方法发生异常"+e);
throw e;
}
finally
{
System.out.println(pjp.getSignature().getName()+"方法发生结束");
}
}
}
常用增强处理类型(主要是一些功能型,日志管理、异常处理、资源释放)
Before 前置增强处理,在目标方法前织入增强处理
AfterReturning 后置增强处理,在目标方法正常执行后织入增强处理(不出现异常情况下,出现异常后置增强不会发生)
AfterThrowing: 异常增强处理,在目标方法抛出异常后织入增强处理
After :最终增强处理,不论方法是否抛出异常,都会在目标方法最后织入增强处理
Around 环绕增强处理,在目标方法前后都可以织入增强处理
SpringAOP配置元素
AOP配置的顶层元素,大多数的必须包含在元素内
定义切点(一般是业务层方法)
定义切面,在切面中进行增强处理类的配置
定义最终增强
定义后置增强
定义异常增强
定义环绕增强
定义前置增强
启动AspectJ注解驱动的切面
使用注解实现IoC的方法(无需在配置文件中配置Bean信息)
注解方式将Bean的定义信息和Bean实现类结合在一起,Spring提供注解有:
@Component:实现Bean组件的定义
@Repository:标注DAO类
@Service:标注业务类
@Controller:标注控制器类
@Repository("userDao") 加了这个等效于在
public class UserDaoImpl implements UserDao{
.....................
}
@Repository("userDao") 加了这个等效于在XML文件编写
使用@Autowired注解执行Bean的自动装配,默认按类型匹配
可以使用@Qualifier指定Bean的名称
第一种方法:
@Service("useServic")
public class UserServiceImpl implements UserService{
@Autowired
@Qualifier("userDao")
private UserDao dao;
.....
}可以对类的成员变量进行标注
第二种方法:
@Service("useServic")
public class UserServiceImpl implements UserService{
private UserDao dao;
@Autowired
public void setDao(@Qualifier("userDao")UserDao dao){
this.dao = dao;
}这种方式可以用在构造方法上面
............
}将UserDao对象引入到UserServiceImpl,相当于配置文件下面的代码
注:@Autowired(required=false) 默认是true,当@Qualifier("userDao2")userDao2未找到,程序不报错会返回一个空指针
使用注解信息启动Spring容器
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.xsd">
package="org.demo"注解类所在的包,多个用逗号分隔
使用@Resource注解执行组件装配,默认按属性名称匹配,如果属性名找不到,就按类型名找
第一种方法
@Service("useServic")
public class UserServiceImpl implements UserService{
@Resource(name="userDao")//通过@Resource注解实现装配
private UserDao dao;
.....
}
第二种方法
public class UserServiceImpl implements UserService{
private UserDao dao;
@Resource(name="userDao")//通过@Resource注解实现装配
public void setDao(UserDao dao){
this.dao = dao;
}
............
}
使用注解实现AOP
AspectJ
面向切面的框架,它扩展了Java语言,定义了AOP语法,能够在编译期提供代码的织入
@AspectJ
AspectJ5新增的功能,使用JDK5.0注解技术和正规的AspectJ切点表达式语言描述切面
注:使用@AspectJ,首先保证所用的JDK是5.0或以上的版本
Spring通过集成AspectJ实现了以注解的方式定义增强类,大大减少了配置文件中的工作量
利用轻量级的字节码处理框架asm处理@AspectJ中所描述的方法参数名
需求说明(使用注解实现日志切面)
使用注解定义前置增强和后置增强实现日志功能
@Aspect
@Before
@AfterReturning
编写Spring文件,完成切面织入
:启用对于@AspectJ注解的支持
@Aspect //定义切面
public class UserServiceLogger {
private static Logger log = Logger.getLogger(UserServiceLogger.class);
/*//前置增强
@Before("execution(void org.demo.UserImpl.addUser(User))")
public void before(JoinPoint jp){
log.info("调用" + jp.getTarget() + "的"+ jp.getSignature() +
"方法.方法参数" + Arrays.toString(jp.getArgs()));
}
//后置增强
@AfterReturning(pointcut="execution(void org.demo.UserImpl.addUser(User))",
returning="result")
public void AfterReturningTest(JoinPoint jp,Object result){
log.info("调用" + jp.getTarget() + "的"+ jp.getSignature() +
"方法.方法返回值" + result);
}*/
//切入点的统一定义
@Pointcut("execution(void org.demo.UserImpl.addUser(User))")
public void pointcut(){}
//前置增强
@Before("pointcut()")
public void before(JoinPoint jp){
log.info("调用" + jp.getTarget() + "的"+ jp.getSignature() +
"方法.方法参数" + Arrays.toString(jp.getArgs()));
}
//后置增强
@AfterReturning(pointcut="pointcut())",returning="result")
public void AfterReturningTest(JoinPoint jp,Object result){
log.info("调用" + jp.getTarget() + "的"+ jp.getSignature() +
"方法.方法返回值" + result);
}
}
配置文件
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
使用注解进行异常增强
@AfterThrowing
使用注解进行最终增强
@After
使用注解进行环绕增强
@Around
使用注解方式定义切面可以简化配置工作量
领取专属 10元无门槛券
私享最新 技术干货