系列文章目录
第一章 基础知识、数据类型学习
第二章 万年历项目
第三章 代码逻辑训练习题
第四章 方法、数组学习
第五章 图书管理系统项目
第六章 面向对象编程:封装、继承、多态学习
第七章 封装继承多态习题
第八章 常用类、包装类、异常处理机制学习
第九章 集合学习
第十章 IO流、多线程学习
第十一章 仓库管理系统项目
第十二章 员工管理系统、多表查询、反射实现DBHelper学习
第十三章 DML、DDL、数据库对象学习
第十四章 网络编程、各种标签、CSS学习
第十五章 ECMAScript、BOM学习
第十六章 DOM、jQuery学习
第十七章 Servlet、jsp、Cookie、Ajax学习
第十八章 融资管理系统项目
第十九章 MyBatis框架学习
第二十章 逆向工程、Spring框架IOC、AOP学习
文章目录
前言
本文会讲述:
逆向工程介绍
Spring框架的介绍与使用
IoC控制反转技术
AOP面向切面技术
在下攸攸太上,正在投骰子决定地球人生死。
一、逆向工程
逆向工程在本文仅做介绍;
逆向工程,名字其实不太符合实际,因为实现的其实是使用代码编写代码,应该叫代码生成工程 ,但多半人类都这么叫,我一个外星人也没法跟他们争。
逆向工程需要配置文件generatorConfig.xml
1. 逆向工程的使用步骤
在配置文件中
1、设置数据库驱动
2、设置生成的pojo实体类的位置
3、设置生成的Mapper映射文件的位置
4、设置生成的Mapper接口的位置
5、根据数据库表生成pojo类
6、执行调用方法
二、初识Spring框架
1. Spring简介
Spring是一个敢于提出新想法的某个略微伟大的人类提出的,为了解决JavaEE项目臃肿低效的问题,Spring的理想是,以Spring调用三层架构,使三层架构关系更加紧密,代码量更少,可扩展性更佳。
Spring分为三个主要的部分IoC(DI)、AOP、TX
IoC控制反转:帮助开发者创建对象,交给Spring容器控制
DL依赖注入:当前类依赖的对象,由Spring容器自动注入
AOP面向切面编程:提高代码的扩展性,有点像过滤器,针对方法
TX声明式事务管理:事务管理机制。事务过程不需要开发者编写,只需要声明出哪些方法需要进行事务管理。
2. IoC控制反转
2.1 IoC介绍
Inversion of Control:实现代码之间的解耦(降低耦合度)
控制:对类实例化的控制,指的是创建对象这个事情。
反转:以前由程序员实例化的过程,转交给Spring进行实例化。
可以想象一下:生成类交给逆向工程、生成对象就交给IoC、释放对象交给垃圾处理机制,此代码要我何用??
但Spring的目标就是这样,一切与逻辑无关的代码交给别人,开发者只管实现逻辑
2.2 IoC代码实现
2.2.1 Dept实体类
package entry;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dept {
private Integer deptno;
private String dname;
private String loc;
}
2.2.2 DeptMapper数据持久层
package mapper;
public class DeptMapper {
public void selectAll(){
System.out.println("I am IronMan");
}
}
2.2.3 DeptService业务层
package service;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import mapper.DeptMapper;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DeptService {
private DeptMapper deptMapper;
public void selectAll(){
deptMapper.selectAll();
}
}
2.2.4 DeptTest控制层
package test;
import entry.Dept;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.DeptService;
public class DeptTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Dept dept = applicationContext.getBean("dept", Dept.class);
dept.setDeptno(100);
dept.setDname("原来如此");
dept.setLoc("原!来!如!此!");
System.out.println(dept);
Dept deptSet = applicationContext.getBean("deptSet", Dept.class);
System.out.println(deptSet);
DeptService deptService = applicationContext.getBean("deptService", DeptService.class);
deptService.selectAll();
}
}
2.2.5 applicationContext框架核心文件
<?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">
<!--设置使用dept的无参构造器创建对象-->
<bean id="dept" class="entry.Dept"/>
<!--设置使用dept的有参构造器创建对象-->
<bean id="deptSet" class="entry.Dept">
<constructor-arg name="deptno" value="199"/>
<constructor-arg index="1" value="客服部"/>
<constructor-arg name="loc" value="南京"/>
</bean>
<!--配置deptMAapper对象-->
<bean id="deptMapper" class="com.jr.mapper.DeptMapper"/>
<!--配置DeptService对象-->
<bean id="deptService" class="com.jr.service.DeptService" autowire="byType">
<!--Spring的属性方式自动注入-->
<!--<property name="deptMapper" ref="deptMapper"/>-->
<!--Spring的构造器方式自动注入-->
<!-- <constructor-arg name="deptMapper" ref="deptMapper"/>-->
</beans>
3. AOP面向切面编程
AOP:Aspect Oriented Programming面向切面编程,目的在于提升代码的扩展性
为了解决“将代码提取出去,还能作用回各个方法”的问题。
按照软件重构思想的理念,在OOP中通过抽象把相同的代码抽取到父类中(纵向抽取),但无法通过抽象父类的方式消除重复性的横切代码(如事务处理这种非业务性的重复代码),而AOP就是为了解决将分散在各个业务逻辑代码中的相同代码通过横向切割的方式抽取到一个独立的模块中。
3.1 什么是切面(举例子)
这么说有些复杂,大家可以想象制作汉堡的流水线,
前提:不同的汉堡,例如:深海鳕鱼堡、香辣鸡腿堡、芝士牛肉堡等,所有的汉堡,里面的汉堡肉不同,但两侧包裹着的面包总是相同的。
代码实现:我们给汉堡肉做成父类,不同的汉堡肉为不同的子类,我们要在每个子类里给不同的汉堡肉夹上相同的面包片,很麻烦对吧?我们可以进行改进
改进plus:我们可以把夹上面包片的方法提取到父类,然后不同的子类都可以调用,很方便对吧!但是我们还可以进行改进
改进ultra:我们把夹上面包片的方法单独提取出来一个类,告诉他,所有的汉堡肉,都夹上面包!
3.2 什么是切面(官方话)
可以理解为程序执行时的某个节点,或者更具体一点,在某个方法执行之前,执行之后等节点。
使用AOP技术,可以将一些系统性相关的编程工作,独立提取出来,独立实现,然后通过切面切入进系统。从而避免了在业务逻辑的代码中混入很多的系统相关的逻辑——比如权限管理,事务管理,日志记录等等。这些系统性的编程工作都可以独立编码实现,然后通过AOP技术再切入进系统即可。从而达到了 将不同的关注点分离出来的效果。
3.3 AOP的应用场合
AOP有特定的应用场合,它只适合具有横切逻辑的应用场合,如:性能检测,访问控制,事务控制,日志记录等。就像面向对象编程的关注点在于对象即类;而面向切面编程的关注的在于切面。
3.4 AOP中的几个要素
1、Aspect :切面,切入系统的一个切面。比如事务管理是一个切面,权限管理也是一个切面;
2、Join point :连接点,也就是可以进行横向切入的位置;
3、Advice :通知,切面在某个连接点执行的操作(分为: Before advice , After returning advice , After throwing advice , After (finally) advice , Around advice );
4、Pointcut :切点,符合切点表达式的连接点,也就是真正被切入的地方;
3.5 AOP的分类
AOP分为静态AOP和动态AOP。静态AOP是将切面代码直接编译到Java类文件中。动态AOP是指先将切面代码统一放到一个切面类里去,然后进行动态织入到指定的切点方法周围,从而实现AOP。Spring的AOP为动态AOP,实现的技术为: JDK提供的动态代理技术和CGLIB(动态字节码增强技术)。尽管实现技术不一样,但 都是基于代理模式,都是生成一个代理对象。
3.6 AOP代码实现
3.6.1 DeptAdvice横切代码类
package com.jr.service;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class DeptAdvice {
@Before("execution(* com.jr.service.DeptService.*(..))")
public void check(){
System.out.println("你谁啊?跟本大爷怎么说话?啊?");
System.out.println("失敬失敬!原来是董事长阁下");
}
@After("execution(* com.jr.service.DeptService.*(..))")
public void log(){
System.out.println("诶!诶!董事长您慢走!");
System.out.println("什么玩意!我恁爹!给爹滚!");
}
}
3.6.2 applicationContext.xml配置文件更新
咱们的Spring框架都是注解来实现的,所以要定义一个扫描路径扫描Spring框架的注解,例如@Aspect、@Componet、@Before、@After等
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<context:component-scan base-package="com.jr"/>
<aop:aspectj-autoproxy/>
<!--加载jdbc属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置数据库环境-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${mysql.driver}"/>
<property name="url" value="${mysql.url}"/>
<property name="username" value="${mysql.username}"/>
<property name="password" value="${mysql.password}"/>
</bean>
<!--配置sqlSessionFactory对象-->
<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:SqlMapConfig.xml"/>
</bean>
<!--配置mapper映射文件的扫描路径-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.jr.mapper"/>
<property name="sqlSessionFactoryBeanName" value="factory"/>
</bean>
<!--配置Spring框架的注解扫描路径-->
<context:component-scan base-package="com.jr"/>
<!--配置spring注解模式下,生成动态代理类-->
<aop:aspectj-autoproxy/>
<!--配置事务管理器对象-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--注解模式下,事务传播策略的配置-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
3.6.3 DeptServiceImpl实现类更新
这回我们将service层写的标准一些,写成结构和实现类的关系。估计大家都能根据以下代码写出DeptService接口类
package com.jr.service.impl;
import com.jr.entry.Dept;
import com.jr.mapper.DeptMapper;
import com.jr.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
@Service
@Transactional(propagation = Propagation.REQUIRED)
public class DeptServiceImpl implements DeptService {
@Autowired //Spring进行自动注入
private DeptMapper deptMapper;
@Override
public ArrayList<Dept> findAll() {
return deptMapper.selectAll();
}
@Override
public boolean addDept(Dept dept) {
return deptMapper.insertDept(dept) == 1 ? true : false;
}
@Override
public boolean updeptDept(Dept dept) {
return deptMapper.updateDept(dept) == 1 ? true : false;
}
}
3.6.4 运行结果
4. TX简介
首先,请看下文中的事务介绍
DML、DDL、数据库对象学习
没看也没关系哦,顶多就是有50%的可能性被我们星球的毁灭光线BiuBiu死。
。
。
。
恭喜你,是剩下的50%,简单来说,事务就是将一段连续的操作视为一个整体,一人失败全员回滚。
二次元看过来!!
这个事务,分明就是抄袭吉良吉影的败者食尘!!
玩笑就开到这里
下面我们更改我们的代码
首先在数据库中运行如下代码:
alter table dept add constraint ck_dept_loc check (loc != '北京' );
此代码能让dept表加入一个约束,使得loc列不能设为“北京”
其次将DeptServiceImpl类里的findAll方法改为如下:
@Override
public ArrayList<Dept> findAll() {
System.out.println("22222222");
Dept dept = new Dept();
dept.setDeptno(122);
dept.setDname("产品部");
dept.setLoc("哈尔滨");
int i = deptMapper.insertDept(dept);
dept.setLoc("北京");
i+=deptMapper.updateDept(dept);
if(i==2){
return deptMapper.selectAll();
}else
return null;
}
这段代码先进行新增操作,后进行修改操作,最后可能进行查询操作。
如果数据库版本较低,loc修改为北京不会成功,因为约束不允许,所以所有操作都会回滚,数据库里
但如果数据库版本高,他可能会认为你是误操作,会报错但是修改操作也会成功。
最后在applicationContext.xml配置文件中加入如下代码:
<!--事物的管理对象-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--注解模式下,事务传播策略的配置-->
<tx:annotation-driven transaction-manager="transactionManager"/>
总结
本文讲述了:
逆向工程:使用代码生成代码;
Spring框架:操作Service层,使Service层的代码量更少,可扩展性更佳;
IoC控制反转技术:创建一个对象帮你创建所有其他对象;
AOP面向切面技术:自动向所有功能的前后添加检查或记录的功能
在下是攸攸太上,我认为地球人都是大low炮。哇哈哈哈哈哈哈哈哈!