Spring 教程(一)
Spring 基本概述
1.1 Spring是什么
spring框架是于2003年兴起的一个轻量级的java开发框架,有Rod Johnson创建,是针对bean的生命周期进行管理的轻量级容器,使现有的技术更加容易使用,简单来说Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架 !
1.2 Spring的优点
1)方便解耦,简化开发
通过Spring提供的IOC容器,可以将对象间的依赖关系交友Spring进行控制,避免硬编码所造成的过度耦合。
2)AOP编程的支持
通过Spring的AOP功能,方便进行面向切面编程,许多不容易用传统OOP实现的功能可以通过AOP轻松实现。
3)声明式事务的支持
可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务管理,提高开发效率和质量。
4)方便程序的测试
可以使用非容器依赖的编程方式进行几乎所有的测试工作,测试不在是昂贵的操做,而是随手可做的事情。
5)方便集成各种优秀框架
Spring对各种优秀框架(Struts,Hibernate,Hessian,Quartz等)的支持
6)降低javaaEE API的使用难度
Spring对javaEE API (如jdbc,javaMail,远程调用等) 进行了薄薄的封装,使这些API的使用难度大大降低
1.3 组成
什么是IOC
1. IOC本质
控制反转,是一种设计思想,DI(依赖注入) 是实现IOC的一种方法,通过描述(xml或者注解)并通过第三方去生产或获取特定对象的方法,在spring中实现控制反转的是IOC容器,其实现方法是依赖注入
2.xml方式开发
2.1 传统应用程序的队友是由程序本身控制创建,在哪里使用就在哪里new 对象
Users users = new Users(); //无参构造,通过set注入属性值
users.setUserId(1L);
users.setUserName("张三");
users.setUserPwd("123456");
Users users1 = new Users(1L,"张三","123456"); //全参构造
System.out.println(users.toString());// Users: userId=1,userName:张三,userPwd:123456;
System.out.println(users1.toString());// Users: userId=1,userName:张三,userPwd:123456;
2.2 Spring 创建bean
1)首先创建一个maven工程,在pom.xml文件中导入Spring的依赖
<!--测试-->
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version><scope>test</scope>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.2.9.RELEASE</version>
</dependency>
<!--spring核心包-->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.9.RELEASE</version>
</dependency>
2) 在resources包下创建applicationContext.xml配置文件,是Spring配置文件约定俗成的名字
3)在applicationContext.xml配置Users,这个时候bean没有被创建,当调用getBean()方法时才会实例化bean
4)bean的依赖注入,在applicationContext.xml通过构造函数,和set注入
数组,集合等数据类型,没写,请百度
<?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.xsd"><!--这里就配置了Users的实例方法,等同于new Users(); --><bean id="users" class="cn.zb.spring.entity.Users" scope="singleton"><!--默认使无参构造,下面使用有参构造,根据参数名,进行赋值--><!--<constructor-arg index="0" value="1"/> 根据参数下标进行赋值--><constructor-arg name="userId" value="1"/><constructor-arg name="userName" value="张三"/><constructor-arg name="userPwd" value="123"/><!--使用set注入属性值--><!--基本数据类型--><property name="userId" value="1"/></bean>
</beans>
spring提供IOC容器实现两种方式
BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供给开发任意使用
ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员使用
测试,通过applicationContext.xml配置文件获得User实例对象
ApplicationContext context=new ClassPathXmlApplicationContext("application.xml");
Users users = context.getBean("users", Users.class);
System.out.println(users.toString()); //Users: userId=1,userName:张三,userPwd:123;
5)bean的作用域
6)bean的自动装配
ByName:会自动在容器上下文中查找,和自己对象方法set对象后面的值对应的bean id,需要保证所有bean的id唯一
ByType:会自动在容器上下文中查找,和自己对象属性类型相同的bean,需要保证所有bean的class唯一
3.注解方式开发
3.1Spring原始注解
spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发时一种趋势,注解代替xml配置,提高开发效率
3.2 Spring新注解
使用新注解就是为了实现用注册代替原始注解不能表示的内容,全面替代之前的核心配置文件applicationContext.xml,使用核心配置类来进行配置,SpringConfiguration是核心配置类
package cn.zb.spring;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@Configuration
@ComponentScan("cn.zb.spring")
public class SpringConfiguration {
}
UserService是接口,包含show()方法;
package cn.zb.spring.service.impl;import cn.zb.spring.entity.Users;
import cn.zb.spring.service.UserService;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;//<bean id="userServiceImpl" class="cn.zb.spring.service.impl.UserServiceImpl">
//@Component("userServiceImpl")
//@Scope("singleton")
@Service
public class UserServiceImpl implements UserService {@Overridepublic void show(Users users) {System.out.println(users.toString());}@PostConstruct@Overridepublic void init() {System.out.println("初始化方法"); //在初始化以前执行}@PreDestroy@Overridepublic void destroy() {System.out.println("销毁方法"); //在容器销毁前执行,但是要改成手动关闭容器才行}
}
3.3 Spring集成Junit测试
1)编写测试类
package cn.zb.test;import cn.zb.spring.SpringConfiguration;
import cn.zb.spring.entity.Users;
import cn.zb.spring.service.UserService;
import cn.zb.spring.service.impl.UserServiceImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import javax.annotation.Resource;@RunWith(SpringJUnit4ClassRunner.class) //替换原来的运行期
@ContextConfiguration(classes = {SpringConfiguration.class}) //指定配置文件或配置类
public class SpringJunitTest {@Autowired //注入对象//@Qualifier("userServiceImpl")//@Resourceprivate UserServiceImpl userService;@Testpublic void test(){//Users users=new Users();ApplicationContext context=new ClassPathXmlApplicationContext("application.xml");Users users = context.getBean("users", Users.class);userService.show(users); //Users: userId=1,userName:张三,userPwd:123;}}
什么是AOP
1.AOP简介
AOP 是面向切面 Aspect-oriented programming(方法)的编程的简写,AOP的实现可以把业务逻辑和系统级的服务进行隔离,是业务逻辑与各个系统级服务的耦合度降低,从而提高程序的重用性和开发效率,AOP的底层实现原理是动态代理。
下面的案例是基于JDK动态代理,JDK动态代理机制只能代理实现了接口的类
package cn.zb.spring.dao;import cn.zb.spring.service.UserService;
import cn.zb.spring.service.impl.UserServiceImpl;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class UserDao {private UserServiceImpl userServiceImpl=new UserServiceImpl();/*** getClassLoader() : 类加载器,用于加载代理类,使用真实对象的类加载器* getInterfaces() : 真是对象所实习的接口,代理模式真实对象和代理对象实现相同的接口* InvocationHandler() : 代理对象的调用处理程序*/public UserService getProxyObject(){UserService userService=(UserService) Proxy.newProxyInstance(userServiceImpl.getClass().getClassLoader(),userServiceImpl.getClass().getInterfaces(),new InvocationHandler() {/*** proxy : 代理对象* method : 对应于在代理对象上调用的接口方法的Method实例* args : 代理对象调用接口方法是传递的实际参数*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result = method.invoke(userServiceImpl, args);return result;}});return userService;}
}
@Test
public void test3(){Users users = new Users(1L,"张三","123456");UserDao userDao=new UserDao();UserService proxyObject = userDao.getProxyObject();proxyObject.show(users); //Users: userId=1,userName:张三,userPwd:123456;
}
2.什么是AspectJ
对于AOP的这种编程思想,由很多框架或者组件进行了实现,Spring实现AOP就是其中一种,AspectJ也实现了AOP而且实现方式更为简单,使用起来更为方便,所以Spring将AspectJ对于AOP的实现引入了自己的框架中。
2.1 AOP的几个术语
1)横切关注点
跨越应用程序多个模块的方法或功能,就是与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点,如日志,安全,缓存,事务等待
2)连接点
连接点是在应用执行中能够切入切面的一个点,即程序执行过程中能购应用通知的所有点
3)切点
切点是真正需要插入切面的一个或多个连接点,即通知被应用的具体位置,通常使用明确的类和方法名称,或是利用正则表达式定义所匹配的类和方法名称来指定这些点(比如Aspect切点表达式)
4)通知
切面的工作被成为通知。即包含了需要多个应用对象的横切行为
AspectJ的通知类型
@Before 前置通知
@Around 环绕通知
@AfterReturning 后置通知
@AfterThrowing 异常通知
@After 最终通知,不管是否异常,该通知都会执行
5)切面
切面式通知和切点的结合,通知和切点共同定义了切面的全部内容
6)织入
织入式把切面应用到目标对象并创建新的代理对象的过程,切面在指定的连接到被织入到目标对象中,在目标对象的生命周期里有多个点可以进行织入(编译期,类加载期,运行期)
7)引入
引入指定的是现有的类添加新方法或属性
2.2 Spring配置AspectJ
1)引入依赖
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.6</version>
</dependency>
2)使用xml方式配置
<bean id="userServiceImplProxy" class="cn.zb.spring.service.impl.UserServiceImplProxy"/>
<!--配置aop增强-->
<aop:config><!--切入点--><aop:pointcut id="p" expression="execution(* cn.zb.spring.service.impl.UserServiceImpl.show(..))"/><!--配置切面--><aop:aspect ref="userServiceImplProxy"><!--增强方法作用在具体方法上--><aop:before method="beforeAdvice" pointcut-ref="p"/></aop:aspect>
</aop:config>
3)使用注解@Aspect创建切面
方法切入语法:
execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
package cn.zb.spring.service.impl;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect
@Component
public class UserServiceImplProxy {//相同切入点提取@Pointcut(value ="execution(* cn.zb.spring.service.impl.UserServiceImpl.show(..))")public void executions(){};@Before(value = "executions()")public void beforeAdvice(){System.out.println("前置通知");}@After(value = "executions()")public void afterAdvice(){System.out.println("最终通知");}@Around(value = "executions()")public void aroundAdvice(ProceedingJoinPoint pjp) throws Throwable{System.out.println("环绕通知,在方法运行前执行");pjp.proceed();System.out.println("环绕通知,在方法运行后执行");}@AfterReturning(value = "executions()")public void afterReturningAdvice(){System.out.println("后置通知");}@AfterThrowing(value = "executions()")public void afterThrowingAdvice(){System.out.println("异常通知");}}
4)启用自动代理
在SpringConfiguration配置类添加注解@EnableAspectJAutoProxy
5)测试类运行,查看结果
本文做记录使用,参考了其他的文献
Spring集成数据库,mybatis在后面的Spring 教程(二)
Spring 教程(一)相关推荐
- Spring教程 - Spring核心框架教程
Spring教程 - Spring核心框架教程 Spring是最广泛使用的Java EE框架之一.我已经在Spring Tutorial上写了很多内容,这是一篇摘要文章,它将作为索引按顺序完成所有这些 ...
- HowToDoInJava Spring 教程·翻译完成
原文:HowToDoInJava 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远. ApacheCN 学习资源 目录 Spring 5 Spr ...
- Spring教程– Spring Core Framework教程
Spring is one of the most widely used Java EE frameworks. I have written a lot on Spring Tutorial an ...
- 【Java】Spring 教程
Spring 教程 Spring 概述 三层架构 Spring 的优良特性 使用 Spring 框架的好处 依赖注入(DI) Spring 框架具有以下几个特点: 1)方便解耦,简化开发 2)方便集成 ...
- Spring教程(由浅入深)
1.Spring教程(由浅入深) 1.1.简介 2002年,Rod Jahnson首次推出了Spring框架雏形interface21框架. 2004年3月24日,Spring框架以interface ...
- Spring 教程(三) 环境设置
环境设置 本教程将指导你如何准备开发环境来使用 Spring 框架开始你的工作.本教程还将教你在安装 Spring 框架之前如何在你的机器上安装 JDK,Tomcat 和 Eclipse. 第 1 步 ...
- Spring教程:使用Spring框架和Spring Boot创建Hello World REST API
由于Java社区对早期版本的Enterprise Java感到失望,因此创建了Spring Framework . 从那时起,它已经发展成为一个巨大的生态系统,可以解决构建基于Web的Java应用程序 ...
- ZetCode Spring 教程
来源:ApacheCN ZetCode 翻译项目 译者:飞龙 协议:CC BY-NC-SA 4.0 贡献指南 本项目需要校对,欢迎大家提交 Pull Request. 请您勇敢地去翻译和改进翻译.虽然 ...
- 【Spring】Spring教程入门到精通
文章目录 1.前言 2.Spring 2.1 Spring的优点 2.2 Spring下载配置 3.IOC 3.1 IOC的处理过程 3.2 IOC底层原理 3.3 IOC接口 3.4 IOC操作Be ...
最新文章
- Unity3D在iOS下为啥不能更新的资料收集
- hyper-V环境下虚拟机和宿主机之间时钟不统一
- 万达与IBM联手发力公有云市场,为不让马云当首富王健林也是拼了
- php布尔类型代码,php中的boolean(布尔)类型详解
- 【ArcGIS】安装ArcEngine 10的顺序
- vue 组件中的钩子函数 不能直接写this
- 前几天入手一大菠萝,写个初始化教程
- A Python example for HiveServer2
- 我们应该改变Linux的二十四件事
- 自旋锁 轻量锁_Java知识进阶-程序员升往架构师必经之路-自旋锁-知识铺
- 如何设置二级标题:当鼠标放到一级标题上二级标题才会显示出来
- 大数运算(加、减、乘、除)
- 如何在南方CASS中内插高程点
- 绿色到黄色到红色的颜色渐变实现
- plist图片列表分割拆分器(修复输出图片错误的BUG)
- 第一次写正规论文的同学务必分享,排版自动排版,加注释。。。。。。等等!!!!!!!!(copy也得整出档次来啊,这就是门面啊)
- win7电脑微信可以登录,但是网页无法访问
- it计算机职业评估,最新澳洲技术移民评估ACS 职业评估(计算机IT类)
- python数据分析与挖掘实战(商品零售购物篮分析)
- 做为站长眼光要放在远方