注解实现IOC_准备工作
注解配置和xml配置对于Spring的IOC要实现的功能都是一样的,只是配置的形式不一样。
准备工作
1 创建一个新的Spring项目。
2 编写pojo,dao,service类。
3 编写空的配置文件,如果想让该文件支持注解,需要添加新的约束:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> </beans>
注解实现IOC_@Component
作用:用于创建对象,放入Spring容器,相当于
位置:类上方
注意:
1、要在配置文件中配置扫描的包,扫描到该注解才能生效。
<context:component-scan base-package="com.itbaizhan"></context:component-scan>
2、@Component 注解配置bean的默认id是首字母小写的类名。也 可以手动设置bean的id值。
// 此时bean的id为studentDaoImpl @Component public class StudentDaoImpl implements StudentDao{ public Student findById(int id) { // 模拟根据id查询学生 return new Student(1,"程序员","北京"); } } // 此时bean的id为studentDao @Component("studentDao") public class StudentDaoImpl implements StudentDao{ public Student findById(int id) { // 模拟根据id查询学生 return new Student(1,"程序员","北京"); } }
注解实现IOC_@Repository、@Service、@Controller
作用:这三个注解和@Component的作用一样,使用它们是为了区 分该类属于什么层。
位置:
1、@Repository用于Dao层
2、@Service用于Service层
3、@Controller用于Controller层
@Repository public class StudentDaoImpl implements StudentDao{} @Service public class StudentService {}
注解实现IOC_@Scope
作用:指定bean的创建策略
位置:类上方
取值:singleton prototype request session globalsession
@Service @Scope("singleton") public class StudentService {}
注解实现IOC_@Autowired
作用:从容器中查找符合属性类型的对象自动注入属性中。用于代替<bean> 中的依赖注入配置。
位置:属性上方、setter方法上方、构造方法上方。
注意:
1、@Autowired 写在属性上方进行依赖注入时,可以省略setter方法。
@Component public class StudentService { @Autowired private StudentDao studentDao; public Student findStudentById(int id) { return studentDao.findById(id); } } @Test public void t2(){ ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); StudentService studentService =(StudentService)ac.getBean("studentService"); System.out.println(studentService.findStudentById(1)); }
2、容器中没有对应类型的对象会报错
// 如果StudentDaoImpl没有放到容器中会报错 //@Component("studentDao") public class StudentDaoImpl implements StudentDao{ public Student findById(int id) { // 模拟根据id查询学生 return new Student(1,"程序员","北京"); } }
3 、容器中有多个对象匹配类型时,会找beanId等于属性名的对 象,找不到会报错。
// 如果容器中都多个同类型对象,会根据id值等于属性 名找对象 @Component("studentDao") public class StudentDaoImpl implements StudentDao{ public Student findById(int id) { // 模拟根据id查询学生 return new Student(1,"程序员","北京"); } } @Component public class StudentDaoImpl implements StudentDao{ public Student findById(int id) { // 模拟根据id查询学生 return new Student(1,"程序员","北京"); } }
注解实现IOC_@Qualifier
作用:在按照类型注入对象的基础上,再按照bean的id注入。
位置:属性上方
注意:@Qualifier必须和@Autowired一起使用。
@Component public class StudentService { @Autowired @Qualifier("studentDaoImpl2") private StudentDao studentDao; public Student findStudentById(int id){ return studentDao.findById(id); } }
注解实现IOC_@Value
作用:注入String类型和基本数据类型的属性值。
位置:属性上方
用法:
1 、直接设置固定的属性值
@Service public class StudentService { @Value("1") private int count; @Value("hello") private String str; }
2 、获取配置文件中的属性值:
2.1 、编写配置文件db.properties
jdbc.username=root jdbc.password01=123456
2.2、spring核心配置文件扫描配置文件
<context:property-placeholder location="db.properties"> </context:property-placeholder>
2.3 注入配置文件中的属性值
@Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password;
注解实现IOC_@Configuration
此时基于注解的IOC配置已经完成,但是我们依然离不开Spring的 xml配置文件。接下来我们脱离bean.xml,使用纯注解实现IOC。
在真实开发中,我们一般还是会保留xml配置文件,很多情况下使用配置文件更加方便。
纯注解实现IOC需要一个Java类代替xml文件。这个Java类上方需要 添加@Configuration,表示该类是一个配置类,作用是代替配置文件。
@Configuration public class SpringConfig { }
注解实现IOC_@ComponentScan
作用:指定spring在初始化容器时扫描的包。
位置:配置类上方
@Configuration @ComponentScan("com.itbaizhan") public class SpringConfig { }
注解实现IOC_@PropertySource
作用:代替配置文件中的<context:property-placeholder> 扫描配置文件
位置:配置类上方
注意:配置文件位置前要加关键字 classpath
@Configuration @PropertySource("classpath:db.properties") public class JdbcConfig { @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; }
注解实现IOC_@Bean
作用:将方法的返回值对象放入Spring容器中。如果想将第三方类 的对象放入容器,可以使用@Bean
位置:配置类的方法上方。
属性:name:给bean对象设置id
注意:@Bean修饰的方法如果有参数,spring会根据参数类型从容 器中查找可用对象。
举例:如果想将jdbc连接对象放入Spring容器,我们无法修改 Connection源码添加@Component,此时就需要使用将@Bean该 对象放入Spring容器
1 、添加驱动依赖
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.27</version> </dependency>
2、将Connection对象放入Spring容器
@Bean(name = "connection") public Connection getConnection(){ try { Class.forName("com.mysql.cj.jdbc.Driver"); returnDriverManager.getConnection("jdbc:mysql:///mysql", "root", "root"); } catch (Exception exception) { return null; } }
3、测试
@Test public void t5(){ ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class); Connection connection = (Connection)ac.getBean("connection"); System.out.println(connection); }
注解实现IOC_@Import
作用:如果配置过多,会有多个配置类,该注解可以为主配置类导入其他配置类
位置:主配置类上方
// Jdbc配置类 @Configuration public class JdbcConfig { @Bean(name = "connection") public Connection getConnection(){ try { Class.forName("com.mysql.cj.jdbc.Driver"); return DriverManager.getConnection("jdbc:mysql:///mysql", "root", "root"); } catch (Exception exception) { return null; } } } // 主配置类 @Configuration @ComponentScan("com.itbaizhan") @Import(JdbcConfig.class) public class SpringConfig { }
Spring整合MyBatis_搭建环境
我们知道使用MyBatis时需要写大量创建 SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession等对 象的代码,而Spring的作用是帮助我们创建和管理对象,所以我们 可以使用Spring整合MyBatis,简化MyBatis开发。
创建maven项目,引入依赖。
<dependencies> <!-- mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> <!-- mysql驱动包 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.26</version> </dependency> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.13</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.3.13</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.13</version> </dependency> <!-- MyBatis与Spring的整合包,该包可以让Spring创建MyBatis的对象 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.6</version> </dependency> </dependencies>
Spring整合MyBatis_编写配置文件
1、编写数据库配置文件db.properties
jdbc.driverClassName = com.mysql.jdbc.Driver jdbc.url = jdbc:mysql:///student jdbc.username = root jdbc.password01 = root
2、创建MyBatis配置文件SqlMapConfig.xml,数据源、扫描接口都 交由Spring管理,不需要在MyBatis配置文件中设置。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> </configuration>
3、创建Spring配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 包扫描 --> <context:component-scan base-package="com.itbaizhan"></context:component-scan> <!-- 读取配置文件 --> <context:property-placeholder location="classpath:db.properties"></context:property-placeholder> <!-- 创建druid数据源对象 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- Spring创建封装过的SqlSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- Spring创建封装过的SqlSession --> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> </beans>
Spring整合MyBatis_准备数据库和实体类
准备数据库
CREATE DATABASE `student`; USE `student`; DROP TABLE IF EXISTS `student`; CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `sex` varchar(10) DEFAULT NULL, `address` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; insert into `student`(`id`,`name`,`sex`,`address`) values (1,'程序员','男','北京'),(2,'北京学堂','女','北京');
准备实体类
public class Student { private int id; private String name; private String sex; private String address; // 省略构造方法/getter/setter/tostring }
Spring整合MyBatis_编写持久层接口和service类
编写持久层接口
@Repository public interface StudentDao { // 查询所有学生 @Select("select * from student") List<Student> findAll(); // 添加学生 @Insert("insert into student values(null,#{name},#{sex},#{address})") void add(Student student); }
编写service类
@Service public class StudentService { // SqlSession对象 @Autowired private SqlSessionTemplate sqlSession; // 使用SqlSession获取代理对象 public List<Student> findAllStudent(){ StudentDao studentDao = sqlSession.getMapper(StudentDao.class); return studentDao.findAll(); } }
Spring整合MyBatis_Spring整合Junit进行单元测试
之前进行单元测试时都需要手动创建Spring容器,能否在测试时让 Spring自动创建容器呢?
1 、引入Junit和Spring整合Junit依赖
<!-- junit,如果Spring5整合junit,则junit版本 至少在4.12以上 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- spring整合测试模块 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.3.13</version> </dependency>
2 、编写测试类
// JUnit使用Spring方式运行代码,即自动创建spring容器。 @RunWith(SpringJUnit4ClassRunner.class) // 告知创建spring容器时读取哪个配置类或配置文件 // 配置类写法: @ContextConfiguration(classes=配置类.class) @ContextConfiguration(locations="classpath:applicationContext.xml") public class StudentServiceTest { @Autowired private StudentService studentService; @Test public void testFindAll(){ List<Student> allStudent = studentService.findAllStudent(); allStudent.forEach(System.out::println); } }
注:使用SqlSessionTemplate创建代理对象还是需要注册接口 或者映射文件的。
1、在MyBatis配置文件注册接口
<configuration> <mappers> <mapper class="com.itbaizhan.dao.StudentDao"></mapper> </mappers> </configuration>
2、创建sqlSessionFactory时指定MyBatis配置文件
<!-- 创建Spring封装过的SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="configLocation" value="classpath:SqlMapConfig.xml"></property> </bean>
Spring整合MyBatis_自动创建代理对象
Spring提供了MapperScannerConfigurer对象,该对象可以自动扫 描包创建代理对象,并将代理对象放入容器中,此时不需要使用 SqlSession手动创建代理对象。
1、创建MapperScannerConfigurer对象
<!-- 该对象可以自动扫描持久层接口,并为接口创建代理对象 --> <bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 配置扫描的接口包 --> <property name="basePackage" value="com.itbaizhan.dao"></property> </bean>
2、Service类直接使用代理对象即可
@Service public class StudentService { // 直接注入代理对象 @Autowired private StudentDao studentDao; // 直接使用代理对象 public void addStudent(Student student){ studentDao.add(student); } }
3、测试
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations="classpath :applicationContext.xml") public class StudentServiceTest { @Autowired private StudentService studentService; @Test public void testAdd(){ Student student = new Student(0, "百战不败", "男", "上海"); studentService.addStudent(student); } }
SpringAOP_AOP简介
AOP的全称是Aspect Oriented Programming,即面向切面编程。 是实现功能统一维护的一种技术,它将业务逻辑的各个部分进行隔 离,使开发人员在编写业务逻辑时可以专心于核心业务,从而提高 了开发效率。
作用:在不修改源码的基础上,对已有方法进行增强。
实现原理:动态代理技术。
优势:减少重复代码、提高开发效率、维护方便
应用场景:事务处理、日志管理、权限控制、异常处理等方面。
SpringAOP_AOP相关术语
为了更好地理解AOP,就需要对AOP的相关术语有一些了解
SpringAOP_AOP入门
AspectJ是一个基于Java语言的AOP框架,在Spring框架中建议使用 AspectJ实现AOP。
接下来我们写一个AOP入门案例:dao层的每个方法结束后都可以 打印一条日志:
1、引入依赖
<!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.13</version> </dependency> <!-- AspectJ --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.7</version> </dependency> <!-- junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
2、编写连接点
@Repository public class UserDao { public void add(){ System.out.println("用户新增"); } public void delete(){ System.out.println("用户删除"); } public void update(){ System.out.println("用户修改"); } }
3、编写通知类
public class MyAspectJAdvice { // 后置通知 public void myAfterReturning() { System.out.println("打印日志..."); } }
4、配置切面
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" 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 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"> <context:component-scan base-package="com.itbaizhan"></context:component-scan> <!-- 通知对象 --> <bean id="myAspectJAdvice" class="com.itbaizhan.advice.MyAspectAdvice"></bean> <!-- 配置AOP --> <aop:config> <!-- 配置切面 --> <aop:aspect ref="myAspectJAdvice"> <!-- 配置切点 --> <aop:pointcut id="myPointcut" expression="execution(* com.itbaizhan.dao.UserDao.*(..))"/> <!-- 配置通知 --> <aop:after-returning method="myAfterReturning" pointcutref="myPointcut"/> </aop:aspect> </aop:config> </beans>
5、测试
public class UserDaoTest { @Test public void testAdd(){ ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); UserDao userDao = (UserDao) ac.getBean("userDao"); userDao.add(); } @Test public void testDelete(){ ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); UserDao userDao = (UserDao)ac.getBean("userDao"); userDao.delete(); } @Test public void testUpdate(){ ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); UserDao userDao = (UserDao) ac.getBean("userDao"); userDao.update(); } }