Java大数据开发工程师__Spring学习笔记(待更新)
Posted ChinaManor
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java大数据开发工程师__Spring学习笔记(待更新)相关的知识,希望对你有一定的参考价值。
1.Spring概述
1.1介绍
Spring框架是企业使用最多的框架,没有之一。Spring是一站式框架,称之为一站式框架的原因是Spring可以整合其他框架。
在本课程中我们要学习Spring的内容如下:
Spring IoC:对象工厂及依赖注入;
Spring AOP:面向切面编程技术,为Spring事务管理打下基础。
Spring Transaction management:Spring事务管理。
Spring Web MVC(不包含在本课程内,后面单独学习):简称Spring MVC框架,用来简化JavaWEB开发,当使用Spring MVC框架后,就不用再编写Servlet了。也就不再需要itcast-tools工具中BaseServlet类了。
Spring与其他框架整合:因为我们只学习过MyBatis框架,所以当前我们只学习Spring整合MyBatis框架。
2.IoC入门
2.1什么是IoC
Spring IoC的核心如下:
工厂负责对象生命周期的管理;(spring管理创建与销毁)
对象的依赖由工厂完成注入。(spring维护对象间关系)
Spring提出了对象工厂的概念,由Spring工厂来管理对象的生命周期。所谓对象生命周期指的是从对象的创建一直到对象的销毁都由Spring来管理。我们无需再自己new对象,而是从Spring工厂中获取需要的对象。甚至对象的依赖也由工厂来注入,无需手动注入依赖。
Spring工厂是ApplicationContext接口,通常我们使用的是AnnotationConfigApplicationContext类。其中Spring工厂内部是通过Map类型来维护的。
key value
“userDao1” UserDao实例
“userService1” UserService实例
… …
当我们需要获取工厂中的实例时,只需要调用工厂的getBean(“id”)即可。
@Test
public void test3() {
AnnotationConfigApplicationContext context = …
UserDao userDao = (UserDao) context.getBean(“userDao1”);
…
}
2.2IoC入门案例1(基础案例)
入门案例1 使用IOC的方式创建UserDao对象 调用查询所有方法
思路:
1.目标类上加@Component
创建UserDao类, 书写方法 findAll ,在类上添加注解@component(”名字”),用来告知spring可以通过指定名字来创建该UserDao对象
2.配置类添加@Configuration 和 @ComponentScan
创建配置类 SpringConfiguration,类上添加@Configuration注解和@ComponentScan注解.(作用是用来告知Spring该类是配置类,并要扫描的包有哪些)
3.测试类通过ApplicationContext的getBean(“名字”)获取对象
案例步骤如下:
配置类(SpringConfiguration)
UserDao类
UserDaoTest类
2.2.1 下载Spring
官网:http://spring.io/
下载地址:
http://repo.springsource.org/libs-release-local/org/springframework/spring
解压:(Spring目录结构:)
- docs :API和开发规范.
- libs :jar包和源码.
- schema :约束.
我们上课使用的maven,使用老师发的pom文件即可.
Pom文件也可以从本文档结尾的附录的pom01-Spring入门拷贝
2.2.2 配置类(SpringConfiguration)
任何Spring项目都建议创建配置类,它提供了Spring工厂最基本的配置信息。本案例中该类没有任何内容,只需要添加两个注解。
SpringConfiguration.java
package com.czxy.comfig;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ComponentScan(basePackages = {“com.czxy.dao”})
@Configuration
public class SpringConfiguration {
}
其中@Configuration注解告知Spring当前类是一个配置类;
其中@componentScan注解告知Spring要扫描的包,Spring会扫描并加载指定包下所有类中的注解。
2.2.3 UserDao.java
我们需要在编写UserDao类,同时希望Spring去创建该类实例并添加到工厂中。这需要在类上添加@Component注解,同时指定实例的id。Spring会扫描到UserDao类上的@Component注解。
UserDao.java
package com.czxy.dao;
import org.springframework.stereotype.Component;
@Component(“ud”)
public class UserDao {
public void findAll(){
System.out.println("查询所有");
}
}
2.2.4 UserDaoTest测试类
在测试类中我们需要先创建工厂对象,然后从工厂对象中获取UserDao对象实例。
UserDaoTest.java
package com.czxy.test;
import com.czxy.comfig.SpringConfiguration;
import com.czxy.dao.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestA {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
UserDao userDao = (UserDao) applicationContext.getBean("ud");// new UserDao();
userDao.findAll();
}
}
2.3IoC入门案例2(依赖注入)
入门案例2中我们需要创建UserService类,但我们知道UserServce一定会依赖UserDao类。然后我们让Spring工厂帮助我们完成依赖注入。
步骤如下:
定义UserService类并添加@Component注解;
在UserService类中添加private UserDao userDao依赖;
在userDao成员上添加@Resource注解指定依赖。
SpringConfiguration.java
package com.czxy.comfig;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ComponentScan(basePackages = {“com.czxy.dao”,“com.czxy.service”})
@Configuration
public class SpringConfiguration {
}
UserService.java
package com.czxy.service;
import com.czxy.dao.UserDao;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component(“us”)
public class UserService {
@Resource(name = “ud”)
private UserDao userDao ;//= new UserDao();
public void findAllUsers(){
System.out.println(“开始查找”);
userDao.findAll();
System.out.println(“查找结束”);
}
}
测试类
@Test
public void test02(){
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
UserService userService = (UserService) applicationContext.getBean(“us”);
userService.findAllUsers();
}
测试结果:
2.4IoC入门案例3(面向接口编程)
入门案例3提供dao的接口和实现类、提供service的接口和实现类,程序之间使用接口,将所有实现类交予spring管理,完成程序间的解耦。
步骤如下
编写UserDao接口和实现类,并在实现类中添加@Component注解
编写UserService接口和实现类,并在实现类中添加@Component注解
在userDao成员变量中添加@Resource注解,注入dao的实现类。
编写配置类
编程测试类
dao接口和实现类
public interface UserDao {
public void findAll();
}
@Component(“userDaoImpl”)
public class UserDaoImplA implements UserDao {
public void findAll(){
System.out.println(“A方式 查询所有”);
}
}
service接口和实现类
public interface UserService {
public void findAllUsers();
}
@Component(“userServiceImpl”)
public class UserServiceImplA implements UserService {
@Resource(name = “userDaoImpl”)
private UserDao userDao ;//= new UserDao();
public void findAllUsers(){
System.out.println(“开始查找”);
userDao.findAll();
System.out.println(“查找结束”);
}
}
配置类 不变
@ComponentScan(basePackages = {“com.czxy.dao”,“com.czxy.service”})
@Configuration
public class SpringConfiguration {
}
测试类
@Test
public void test03(){
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
UserService userService = (UserService) applicationContext.getBean(“userServiceImpl”);
userService.findAllUsers();
}
测试结果:
2.5IoC入门案例4(整合JUnit4)
修改测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={SpringConfigruation.class})
public class UserDaoTest {
@Resource(name="userService1")
private UserService userService;
@Test
public void testFindAll(){
userService.findAll();
}
}
3.IoC详解
3.1Bean的创建
前面已经学习了创建Bean的注解@Component,Spring还提供了一些衍生注解。
注解 描述
@Component 将修饰的资源交予spring管理。
value属性:为资源命名(唯一标识)
@Controller 衍生注解,与@Component作用和属性相同。特用于修饰表示层的资源。
@Service 衍生注解,与@Component作用和属性相同。特用于修饰业务逻辑层的资源。
@Repository 衍生注解,与@Component作用和属性相同。特用于修饰数据访问层的资源。
示例: 分别使用不同名字的注解来设置响应的类
@Repository(“userDao1”)
public class UserDaoImpl implements UserDao {
public void findAll(){
System.out.println(“入门案例”);
}
}
@Service(“userService1”)
public class UserServiceImpl implements UserService{
@Resource(name="userDao1")
private UserDao userDao;
public void findAll(){
System.out.println("user service ...");
userDao.findAll();
}
}
以上4个注解修饰的类,我们通常称为注册bean。目的是将某类的实例对象,添加到spring容器中。
3.2依赖注入(DI)
注解 描述 修饰位置
@Resource(name=”…”) 按照指定名称注入对象 字段、setter方法
@ Resource 按照类型注入对象 字段、setter方法
@Value 注入简单值 字段、setter方法、参数
@PropertySource 加载properties配置文件 类
3.2.1按照名称注入
示例: 按照名称来注入userDao对象
dao
@Repository(“userDao1”)
public class UserDaoImpl implements UserDao {
public void findAll(){
System.out.println(“入门案例”);
}
}
service
@Service(“userService1”)
public class UserServiceImpl implements UserService{
@Resource(name="userDao1")
private UserDao userDao;
public void findAll(){
System.out.println("user service ...");
userDao.findAll();
}
}
3.2.2按照类型注入
示例: 分别创建dao ,service ,和测试类,按照类型注入对应的对象
dao
@Repository
public class UserDaoImpl implements UserDao {
public void findAll(){
System.out.println(“入门案例”);
}
}
service
@Service
public class UserServiceImpl implements UserService{
@Resource
private UserDao userDao;
public void findAll(){
System.out.println("user service ...");
userDao.findAll();
}
}
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={SpringConfigruation.class})
public class UserDaoTest {
@Resource
private UserService userService;
@Test
public void testFindAll(){
userService.findAll();
}
}
3.2.3普通数据注入
示例:字符串类型的成员变量和方法参数注入数据.
固定值注入
public class SpringConfigruation {
@Value("com.mysql.jdbc.Driver")
private String driver;
@Value("jdbc:mysql://127.0.0.1:3306/crm_ssm_v1_0")
public void setUrl(String url){
System.out.println("字段:" + driver);
System.out.println("方法:" + url);
}
}
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={SpringConfigruation.class})
public class UserDaoTest {
@Test
public void testFindAll() throws SQLException{
}
}
3.2.4properties数据注入
需求: 把properties文件中的数据读取出来,在测试类中展示
总体思路:
使用@PropertySource加载properties配置文件,“classpath:”固定前缀,表示从类路径下加载配置文件。
@Value(${jdbc.driver}) 获得配置文件中指定key的内容
默认:将整个表达式进行注入,及 driver变量的值是 ${jdbc.driver}
固定代码:必须配置PropertySourcesPlaceholderConfigurer实例。
项目结构如下:
jdbc.properties配置文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/test1
jdbc.username=root
jdbc.password=1234
配置类 添加内容
package com.czxy.demo02;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
@Configuration
@PropertySource(“classpath:db.properties”)
public class SpringConfig02 {
// 在4.2.4版本读取properties必须写,必须要写的固定格式
@Bean
public static PropertySourcesPlaceholderConfigurer create(){
return new PropertySourcesPlaceholderConfigurer();
}
}
测试类:
package com.czxy.demo02;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig02.class)
public class TestB {
@Value("${jdbc.driver}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Test
public void test01(){
System.out.println("driverClassName="+driverClassName);
System.out.println("url="+url);
}
}
测试结果:正常获取数据
3.1@Bean(工厂Bean)
把别人创建的类,交给IOC管理可以使用方法配合注解@Bean的方式实现.
通过@Component等注解,将我们自己编写的对象配置到spring容器中。
通过@Resource等注解,将我们自己编写的对象之间的关系配置到spring容器中。
实际开发中,我们经常会遇到某些类不是我们写的,此时我们希望通过IOC对这种类进行管理,我们就没法办在这个类上加@Component等注解了. 这个时候可以创建一个方法在方法上使用@Bean来实现对这些类对象的管理
3.1.1基本使用:类型注入
@Bean用于修饰方法,将方法创建的对象添加到spring容器
需求: 假设UserDao不是我们写的类,无法使用@Component注解,
创建一个方法用于获取UserDao对象
准备如下几个类
UserDao:
package com.czxy.demo03;
public class UserDao {
public void findAll(){
System.out.println("查询所有 ");
}
}
SpringConfig03:
package com.czxy.demo03;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfig03 {
@Bean
public UserDao getUserDao(){
return new UserDao();
}
}
测试类:
package com.czxy.demo03;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig03.class)
public class TestC {
@Resource
private UserDao userDao;
@Test
public void test01(){
userDao.findAll();
}
}
测试结果:
3.1.2基本使用:指定名称注入
上面例子中,在方法上只是书写了一个@Bean.并没有给期产生的对象命名如果想命名可以通过如下方式.
@Bean(name=”名字”) 可以为当前对象设置一个名称,如果没有使用name设置名称,默认名为“方法名”。
需求:
UserDao是个接口,有俩实现类UserDaoImplA和UserDaoImplB, 这三个类假设我们都不能修改.
现在想获取这俩实现类的对象,交给IOC管理. 设计完成该例子.
项目结构如下:
UserDao接口:
package com.czxy.demo04;
public interface UserDao {
public void findAll();
}
UserDaoImplA实现类:
package com.czxy.demo04;
public class UserDaoImplA implements UserDao {
@Override
public void findAll() {
System.out.println("A 方式实现查询所有用户 ");
}
}
UserDaoImplB实现类:
package com.czxy.demo04;
public class UserDaoImplB implements UserDao {
@Override
public void findAll() {
System.out.println("B 方式实现查询所有用户 ");
}
}
配置类:
package com.czxy.demo04;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfig04 {
@Bean(name ="userDaoImplA" )
public UserDao getUserDaoA(){
return new UserDaoImplA();
}
@Bean(name ="userDaoImplB" )
public UserDao getUserDaoB(){
return new UserDaoImplB();
}
}
测试类:
package com.czxy.demo04;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig04.class)
public class TestD {
@Resource(name = "userDaoImplB")
private UserDao userDao;
@Test
public void test01(){
userDao.findAll();
}
}
测试结果:
userDaoImplB对应:
userDaoImplA对应:
3.1.3 依赖注入:引用类型
当某一个方法的参数是一个被IOC管理的对象时,可以通过@Bean的方式,自动注入该对象.
如UserDao对象被IOC管理了. 那么 若有方法 形如testXXX(UserDao userDao) 则可以在方法上添加@Bean,来自动注入UserDao对象.
示例1:
把UserDao交给IOC
在配置类中书写一个方法show(UserDao userDao),完成自动注入,在测试类中进行测试.
代码详情:
UserDao
package com.czxy.demo06;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
public void findAll(){
System.out.println("查询所有");
}
}
配置类:SpringConfig06
package com.czxy.demo06;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import javax.annotation.Resource;
@Configuration
@ComponentScan(basePackages = “com.czxy.demo06”)
public class SpringConfig06 {
@Bean
public String show(UserDao userDao){
System.out.println("完成自动注入:"+userDao);
//测试调用userDao方法
userDao.findAll();
return null;
}
}
测试类:
package com.czxy.demo06;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig06.class)
public class TestA1 {
@Test
public void test02(){
//无需书写任何代码, 单纯执行
//该方法就会看到自动注入UserDao
}
}
测试结果:
可以看到 完成了自动注入.
示例2:
把UserDao对象存放到spring容器中, 然后再UserService方法中要使用UserDao,此时可以直接把UserDao当做参数传递到方法中
`
配置类:
package com.czxy.demo02.config;
import com.czxy.demo02.dao.UserDao;
import com.czxy.demo02.dao.UserDaoImpl;
import com.czxy.demo02.service.UserService;
import com.czxy.demo02.service.UserServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {“com.czxy.demo02”})
public class SpringConfiguration {
@Bean
public UserDao getUserDao(){
return new UserDaoImpl();
}
@Bean
public UserService getUserService(UserDao userDao){
System.out.println(userDao);
return new UserServiceImpl();
}
}
测试类
package com.czxy.demo02.test;
import com.czxy.demo02.config.SpringConfiguration;
import com.czxy.demo02.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
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 TestA {
@Resource
public UserService userService;
@Test
public void test01(){
System.out.println(userService);
}
}
测试结果:
3.1.4依赖注入:简单类型
需求: 把properties文件中的字符串 以简单类型的方式添加到参数中 打印对应的值.
配置类
相应代码:
@PropertySource(“classpath:db.properties”)
public class SpringConfiguration2 {
@Bean
public static PropertySourcesPlaceholderConfigurer create(){
return new PropertySourcesPlaceholderConfigurer();
}
@Bean
public UserService createUserService(@Value("
j
d
b
c
.
u
s
e
r
n
a
m
e
"
)
S
t
r
i
n
g
n
a
m
e
,
@
V
a
l
u
e
(
"
{jdbc.username}") String name, @Value("
jdbc.username")Stringname,@Value("{jdbc.password}") String pwd){
System.out.println(“name = “+name+” pwd =”+pwd);
return new UserServiceImpl();
}
}
测试类
代码:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration2.class)
public class TestB {
@Resource
private UserService userService;
@Test
public void test01(){
System.out.println(userService);
}
}
测试结果:
3.1Bean的作用域
通过@Scope可以Bean的作用域,也就是通知spring是否每次都创建新对象。
注解 描述 取值
@Scope 用于设置Bean的作用域 singleton :默认值,单例的.
prototype :多例的.
单例模式: 整个IOC容器中只有该实体类的一个对象
多例模式: 整个IOC容器中该实体类有多个对象
示例:
搞一个User类,在配置类中设置单例模式和多例模式,创建两个对象观察效果.
配置类:
测试类:
单例模式结果: 地址编号相同,说明是用的同一个对象
保持测试类不变,只更改为多例模式
测试结果:打印的两个地址编号不同,说明IOC容器中有多个对象
其他取值(了解)
1.request :WEB项目中,Spring创建一个Bean的对象,将对象存入到request域中.
2.session :WEB项目中,Spring创建一个Bean的对象,将对象存入到session域中.
3.globalSession :WEB项目中,应用在Portlet环境.如果没有Portlet环境那么globalSession相当于session
3.2生命周期
生命周期指单实例对象由创建到销毁的整个过程。
此处,主要研究初始化方法和销毁方法。
3.2.1实例Bean
实例Bean同时2个注解,来控制类中那个方法初始化方法,那个方法是销毁方法。
注解 描述
@PostConstruct 初始化方法,项目启动时执行,只会被调用一次。
@PreDestroy 销毁方法,项目关闭时执行,只会被调用一次。
实例Dog
@Component
public class Dog {
@PostConstruct
public void init(){
System.out.println(“狗 初始化”);
}
public void eat(){
System.out.println(“狗 吃吃吃…”);
}
@PreDestroy
public void destory(){
System.out.println("狗 销毁 ");
}
}
配置类
@ComponentScan(basePackages={“com.czxy.domain”})
public class SpringConfigruation {
}
测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class TestC {
@Resource
private Dog dog;
@Test
public void test01(){
dog.eat();
}
}
测试结果 :
3.2.2工厂Bean
工厂Bean通过@Bean的2个属性完 成初始化和销毁方法的配置。
initMethod:配置初始化方法
destroyMethod:配置销毁方法
实体类:
public class Cat {
public void init(){
System.out.println(“猫 初始化”);
}
public void eat(){
System.out.println(“猫 吃吃吃…”);
}
public void destory(){
System.out.println("猫 销毁 ");
}
}
配置类
@Configuration
@ComponentScan(basePackages = {“com.czxy.demo02”})
public class SpringConfiguration {
@Bean(initMethod = “init” ,destroyMethod = “destory”)
public Cat getCat(){
return new Cat();
}
}
测试类:
@Resource
private Cat cat;
@Test
public void test02(){
cat.eat();
}
测试结果:
4.AOP
4.1AOP概述
4.1.1什么是AOP
AOP:全称是Aspect Oriented Programming即:面向切面编程。
面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
简单的说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用代理的技术,在不修改原来代码的基础上,对已有方法进行增强。
4.1.2快速入门1
需求:
User类中有方法eat . 现在在不修改eat方法的前提下,对eat进行增强. 增强的内容是,在执行eat之前,先执行 沐浴更衣 这个动作.
实现思路:
1.搭建基本的测试 可以在测试类中执行eat方法
2.创建切面类,指明对eat方法进行增强;
具体代码如下: 在书写代码之前记得在pom文件添加spring相关的依赖.
User类
@Component
public class User {
public void eat(){
System.out.println(“吃吃吃”);
}
}
配置类:
@Configuration //设置为 配置类
@ComponentScan(basePackages = {“com.czxy.demo01”}) // 设置要扫描的包
@EnableAspectJAutoProxy // 设置 开启切面
public class SpringConfig01 {
}
切面类:
@Component
@Aspect
public class MyAspect01 {
@Before(“execution(public void com.czxy.demo01.User.eat())”)
public void bf01(){
System.out.println("沐浴更衣 ");
}
}
测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes ={SpringConfig01.class})
public class TestA {
@Resource
private User user;
@Test
public void test01(){
user.eat();
}
}
执行结果:
4.1.3AOP作用和优势
作用:
1.在程序运行期间,不修改源码对已有方法进行增强。
优势:
1.减少重复代码
2.提高开发效率
3.维护方便
4.1.4快速入门2
需求: 使用AOP 对UserService接口的两个方法进行增强. 在方法执行之前,开启事务,在方法执行之后关闭事务.
项目结构:
具体代码:
Pom中需要添加aop相关的依赖
UserService接口: 接口中提供两个方法
public interface UserService {
public void addUser();
public void delUser();
}
实现类UserServiceImpl
@Service
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("添加用户 ");
}
@Override
public void delUser() {
System.out.println(“删除用户”);
}
}
配置类:
@Configuration
@ComponentScan(basePackages = “com.czxy.demo02”)
@EnableAspectJAutoProxy
public class SpringConfiguration2 {
}
切面类MyAspect02:
@Component
@Aspect
public class MyAspact02 {
@Before(“execution(public void com.czxy.demo02.UserService.*())”)
public void bf(){
System.out.println(“开启事务”);
}
@After(“execution(public void com.czxy.demo02.UserService.*())”)
public void af(){
System.out.println(“关闭事务”);
}
}
测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration2.class)
public class TestB {
@Resource
private UserService userService;
@Test
public void test01(){
userService.addUser();
System.out.println("----------");
userService.delUser();
}
}
测试结果:
4.1.5快速入门3
需求: 使用AOP 对UserService和BookService接口的方法进行增强.
4.1.6AOP实现方法
Spring AOP 主要通过2种代理技术来实现:动态代理、CGLIB
动态代理:用于对接口+实现类情况进行代理。
@EnableAspectJAutoProxy(proxyTargetClass = false)
CGLIB:用于对仅有类情况进行代理。
@EnableAspectJAutoProxy(proxyTargetClass = true)
4.2相关AOP术语
Target(目标对象):
代理的目标对象。通俗点讲:你需要增强的类,这个类就是目标对象
例如:UserServiceImpl
Joinpoint(连接点):
所谓连接点是指可能被增强的位置。在spring中,AOP是对方法进行增强,这个位置/时机可以是方法前或者方法后,或者出异常的时候。
例如:addUser()方法执行之前的位置 或者 addUser()方法执行之后的位置 或者 AddUser出异常的时候
Pointcut(切入点):
所谓切入点是指我们要对哪些Joinpoint进行拦截的定义。通俗讲:确定了在哪个位置进行增强
例如:@Before(“execution(public void com.czxy.demo02.UserService.addUser())”)
Advice(通知/增强): 具体要干的事情
所谓通知是指拦截到Joinpoint之后所要做的事情就是通知。
通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。
例如:bf()、af()
Aspect(切面):
是切入点和通知的结合。
例如:MyAspect类
Proxy(代理):
一个类被AOP增强后,就产生一个结果代理类。
4.3相关注解
注解 描述
@Aspect 把当前类声明成切面类
@Before 把当前方法看成是前置通知
@AfterReturning 把当前方法看成是后置通知。
@AfterThrowing 把当前方法看成是异常通知
@After 把当前方法看成是最终通知
@Around 把当前方法看成是环绕通知
@Pointcut 指定切入点表达式
4.3.1切入点表达式
execution:
匹配方法的执行(常用)
execution(表达式)
表达式语法:execution([修饰符] 返回值类型 包名.类名.方法名(参数))
写法说明:
全匹配方式:
public void com.itheima.service.impl.CustomerServiceImpl.saveCustomer()
访问修饰符可以省略
void com.itheima.service.impl.CustomerServiceImpl.saveCustomer()
返回值可以使用号,表示任意返回值
* com.itheima.service.impl.CustomerServiceImpl.saveCustomer()
包名可以使用号,表示任意包,但是有几级包,需要写几个*
* ....CustomerServiceImpl.saveCustomer()
使用…来表示当前包,及其子包
* com…CustomerServiceImpl.saveCustomer()
类名可以使用号,表示任意类
* com….saveCustomer()
方法名可以使用号,表示任意方法
* com….()
参数列表可以使用,表示参数可以是任意数据类型,但是必须有参数
* com….()
参数列表可以使用…表示有无参数均可,有参数可以是任意类型
* com….(…)
全通配方式:
* ….(…)
4.3.2通知方法
方式1:没有参数形式
@Before(“execution(public void com.czxy.demo01.User.eat())”)
public void bf01(){
System.out.println("洗手 ");
}
执行效果:
方式2:获得参数JoinPoint,从而获得目标类,目标方法等信息
@Before(“execution(public void com.czxy.demo01.User.eat())”)
public void bf01(JoinPoint jp){
System.out.println("洗手 ");
System.out.println(“目标类:”+jp.getTarget());//获取目标类
System.out.println(“切入点:”+jp.getSignature());//获取切入点
}
执行效果:
方式3:环绕通知获得参数ProceedingJoinPoint,对目标方法的执行进行控制。
@Around(“execution(public void com.czxy.demo01.User.eat())”)
public void ar(ProceedingJoinPoint jp) throws Throwable {
System.out.println("洗手 ");
jp.proceed();//执行 eat方法
System.out.println(“擦嘴”);
}
执行效果:
4.3.3抽取公共切入点
使用@PointCut可以将公共的切入点进行抽取,一般都声明在私有方法上。
在通知注解使用,通过方法名引用。
@Pointcut(“execution(* com.czxy.service….(…))”)
private void myPointcut(){
}
@Before("myPointcut()")
public void bf(JoinPoint joinPoint){
System.out.println("前置..." + joinPoint.getTarget());
System.out.println("前置..." + joinPoint.getSignature().getName());
}
@AfterReturning("myPointcut()")
public void af(){
System.out.println("后置...");
}
4.4完整通知演示
4.4.1AOP编程
编写需要对目标类,增量的类和方法(可以复制)
@Component
@Aspect
public class MyAspect {
@Before("execution(* com.czxy.service..*.*(..))")
public void bf(){
System.out.println("开始");
}
@AfterReturning("execution(* com.czxy.service..*.*(..))")
public void af(){
System.out.println("结束");
}
}
修改配置类
@ComponentScan(basePackages={“com.czxy”})
@EnableAspectJAutoProxy
public class SpringConfigruation {
}
测试
4.4.2目标接口和类
接口
public interface UserService {
public void saveUser();
public String updateUser();
}
实现类
@Service
public class UserServiceImpl implements UserService {
@Override
public void saveUser() {
System.out.println("save");
}
@Override
public String updateUser() {
System.out.println("update");
return "abc";
}
}
4.4.3配置类
@ComponentScan(basePackages={“com.czxy”})
@EnableAspectJAutoProxy
public class SpringConfigruation {
}
4.4.4切面类
@Component
@Aspect
public class MyAspect2 {
@Pointcut("execution(* com.czxy.service..*.*(..))")
private void myPointcut(){
}
@Before("myPointcut()")
public void bf(JoinPoint joinPoint){
System.out.println("前置..." + joinPoint.getTarget());
System.out.println("前置..." + joinPoint.getSignature().getName());
}
@AfterReturning(value="myPointcut()",returning="ret")
public void ar(JoinPoint joinPoint , Object ret){
System.out.println("后置..." + ret);
}
@Around("myPointcut()")
public void ar(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("环绕前");
joinPoint.proceed(); //执行目标方法
System.out.println("环绕后");
}
@AfterThrowing(value="myPointcut()",throwing="ex")
public void at(JoinPoint joinPoint ,Throwable ex){
System.out.println("异常:" + ex.getMessage());
}
@After("myPointcut()")
public void af(){
System.out.println("最终");
}
}
4.4.5测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={SpringConfigruation.class})
public class UserDaoTest {
@Resource
private UserService userService;
@Test
public void testFindAll() throws SQLException{
userService.saveUser();
int i = 1/0;
userService.updateUser();
}
}
5.整合MyBatis
之前使用的持久层框架是MyBatis, 现在将Mybatis框架整合到Spring框架中,由Spring统一管理.其核心思路是把Mapper对应的实现类对象存放在IOC容器中.
需求:
通过Spring+Mybatis整合,把一个用户的信息添加到数据库中.
实现步骤:
1.环境搭建
2.编写Dao和Service
3.书写配置类
4.测试
完整的项目结构如下:
5.1环境搭建
5.1.1导入pom相关的依赖
<spring.version>4.2.4.RELEASE</spring.version>
5.1.2配置文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/test1
jdbc.username=root
jdbc.password=1234
5.1.3创建数据库和表
CREATE TABLE USER(
uid VARCHAR(32) PRIMARY KEY,
username VARCHAR(50),
PASSWORD VARCHAR(32)
)
5.1.4创建domain
public class User {
@Id
private String uid;
private String username;
private String password;
//getter和setter方法
//…
}
5.2编写dao和service
5.2.1编写dao接口
package com.czxy.dao;
import com.czxy.domain.User;
import tk.mybatis.mapper.common.Mapper;
public interface UserMapper extends Mapper {
}
5.2.2编写service接口
package com.czxy.service;
import com.czxy.domain.User;
public interface UserService {
public User findByPrimaryKey(String uid);
public void insertUser(User user);
}
5.2.3编写Service实现类
package com.czxy.service.impl;
import com.czxy.dao.UserMapper;
import com.czxy.domain.User;
import com.czxy.service.UserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Override
public User findByPrimaryKey(String uid) {
return userMapper.selectByPrimaryKey(uid);
}
@Override
public void insertUser(User user) {
userMapper.insert(user);
}
}
5.3配置类
5.3.1spring配置类
1.配置注解
1.1 扫描注解包
1.2加载properties文件
1.3 开启注解事务支持
2.获得properties数据(实现类、@Value)
3.配置数据源DataSource
4.配置事务管理器(DataSourceTransactionManager)
package com.czxy.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;
import javax.annotation.Resource;
import javax.sql.DataSource;
@Configuration
@ComponentScan(basePackages = {“com.czxy”})
@EnableTransactionManagement
@PropertySource(value = “classpath:db.properties”)
public class SpringConfig {
// 4.2.4版本 固定配置
@Bean
public static PropertySourcesPlaceholderConfigurer create(){
return new PropertySourcesPlaceholderConfigurer();
}
//读取数据库相关配置
@Value("
j
d
b
c
.
d
r
i
v
e
r
"
)
p
r
i
v
a
t
e
S
t
r
i
n
g
d
r
i
v
e
r
C
l
a
s
s
;
@
V
a
l
u
e
(
"
{jdbc.driver}") private String driverClass; @Value("
jdbc.driver")privateStringdriverClass;@Value("{jdbc.url}")
private String url;
@Value("
j
d
b
c
.
u
s
e
r
n
a
m
e
"
)
p
r
i
v
a
t
e
S
t
r
i
n
g
u
s
e
r
n
a
m
e
;
@
V
a
l
u
e
(
"
{jdbc.username}") private String username; @Value("
jdbc.username")privateStringusername;@Value("{jdbc.password}")
private String password;
//数据源使用德鲁伊连接池
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driverClass);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
// 开启事务管理器
@Bean
@Resource
public DataSourceTransactionManager txManager(DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
}
5.3.2mybatis配置类【新内容】
如下代码直接当做配置类拷贝即可.
1.配置session工厂,spring和MyBatis整合时,通过SqlSessionFactoryBean获得SqlSessionFactory
SqlSessionFactoryBean只能加载mapper映射文件
注解开发需要加载Mapper类,故需要对mapper进行扫描
2.配置映射扫描器
package com.czxy.config;
import com.github.pagehelper.PageHelper;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tk.mybatis.spring.mapper.MapperScannerConfigurer;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Properties;
/**
-
Spring整合MyBatis的配置类
-
@author Administrator
*/
// 声明
@Configuration
public class MyBatisConfig {/**
-
构建SessionFactory对象,SessionFactory可以创建Session对象,最后使用Session操作数据库
-
@param dataSource
-
@return
-
@throws Exception
*/
@Bean
@Resource
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
// 1.通过工厂bean创建对象,最后需要调用 getObject()获得具体的对象
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
// 1.1 设置数据源
factoryBean.setDataSource(dataSource);
// 1.2 设置别名包扫描
factoryBean.setTypeAliasesPackage(“com.czxy.domain”);
// 1.3 全局配置:驼峰映射
org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration();
config.setMapUnderscoreToCamelCase(true);
factoryBean.setConfiguration(config);// 2 插件配置
// 2.1 分页插件
PageHelper pageHelper = new PageHelper();
Properties pageProps = new Properties();
pageProps.setProperty(“dialect”, “mysql”);
pageProps.setProperty(“rowBoundsWithCount”, “true”);
pageHelper.setProperties(pageProps);
factoryBean.setPlugins(new Interceptor[] { pageHelper });// 3 通过工厂bean获得 sqlSessionFactory
return factoryBean.getObject();
}
/**
- 扫描Dao的包,查找各种XxxMapper接口,创建好UserMapper等对象存入到IOC的容器中
- @return
*/
@Bean
public MapperScannerConfigurer mapperScanner() {
MapperScannerConfigurer configurer = new MapperScannerConfigurer();
configurer.setBasePackage(“com.czxy.dao”);
return configurer;
}
-
}
5.4测试类
5.4.1方式1:整合Junit
package com.czxy.test;
import com.czxy.config.MyBatisConfig;
import com.czxy.config.SpringConfig;
import com.czxy.domain.User;
import com.czxy.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfig.class,MyBatisConfig.class})
public class TestA {
@Resource
private UserService userService;
@Test
public void test01(){
User user = new User(“u001”,“张三丰”,“123”);
userService.insertUser(user);
System.out.println("添加完毕");
}
}
测试结果: 成功添加用户信息
5.4.2方式2:手动创建工厂
public class TestB {
public static void main(String[] args) {
//1.创建工厂,设置两个配置类
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class,MyBatisConfig.class);
//2.从工厂获取需要的对象
UserService userService = applicationContext.getBean(UserService.class);
//3.执行语句
User user = new User("u800","zhangsan","123");
userService.insertUser(user);
System.out.println("添加完毕");
}
}
5.4.3完整的UserService
userService:
public interface UserService {
void addUser(User user);
void updateUser(User user);
void delUser(String uid);
User findByPrimaryKey(String uid);
List findAll();
List findByPage();
}
userServiceImpl:
@Service
@Transactional // 第五节讲解
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
public void addUser(User user) {
userMapper.insert(user);
}
public void updateUser(User user) {
userMapper.updateByPrimaryKey(user);
}
public void delUser(String uid) {
userMapper.deleteByPrimaryKey(uid);
}
public User findByPrimaryKey(String uid) {
return userMapper.selectByPrimaryKey(uid);
}
public List<User> findAll() {
return userMapper.selectAll();
}
public List<User> findByPage() {
// PageHelper
// 第一个参数:第几页
// 第二个参数:获取条数 ,PageHelper这个代码后的第一个sql语句进行分页
PageHelper.startPage(1, 2);
// 查找
// userMapper.selectAll();
List list = userMapper.select(null);
// 封装到pageInfo
PageInfo<User> info = new PageInfo<User>以上是关于Java大数据开发工程师__Spring学习笔记(待更新)的主要内容,如果未能解决你的问题,请参考以下文章