相关文档:
https://cntofu.com/book/95/index.html
http://wiki.jikexueyuan.com/project/spring
matools.com
spring5中的事务底层原理是AOP
目录
1、导入相关jar包 druid-1.1.9(数据库连接包) mysql-connector-java-5.1.7-bin
3、相关逻辑类:如转账业务Entity(Account包含用户名和金额)
一、 srping概述
1轻量级javaEE框架
2 核心组成IOC和AOP
IOC:控制反转,spring创建对象并进行依赖注入,A依赖对象B,由原来的主动创建变为被动的注入,A对B由主动控制变为被动拥有。
AOP:面向切面,在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。
3 下载安装:
下载https://repo.spring.io/ui/repos/tree/General/libs-release-local/org/springframework/spring
解压后选择相关jar包复制到程序中,项目添加jar包。
核心jar包:bean,core,context,expression
辅助jar包:logging,aop……
二、IOC
1、入门案例
xml配置bean实例:
<bean id="user" class="com.spring5.User"></bean>
public void test(){
ApplicationContext context=new ClassPathXmlApplicationContext("userBean.xml");
System.out.println("生命周期第四步 获取实例 执行相关方法");
User user = context.getBean("user", User.class);
System.out.println("获取到user实例:"+user+"将执行add方法如下:");
user.add();
}
2、 IOC定义
: IOC(Inversion of control)控制反转,将创建和对象间的调用依赖交给spring管理。目的是降低对象间的耦合 底层原理 xml解析,工厂模式,反射。
3、IOC对bean的管理
xml和注解,两种方式都可以对实现,注解是对xml的一种简化,关于两种方式的比较https://blog.csdn.net/weixin_40341116/article/details/80939194
(1)创建对象
(2)注入属性
4 注解方式管理bean
(1)引入jar包:spring-aop
(2)开启组件扫描
先要引入context命名空间
设置扫描配置<context:component-scan ……
可以设置扫描过滤条件 include-filter exclude-filter
(3)创建对象注入属性相关注解
创建对象类级别注解:Component Service(业务层) Controller(web层) Respository(持久层)
属性方法注解:
AutoWired: Spring管理的bean发现有这个注解时候,它会直接注入相应的另一个Spring管理的bean。当有相同类型的bean时可与Qualifier一同使用:
@Qualifier(value="comment1")
@Autowired
private Comment firstComment;
@Qualifier(value="comment2")
@Autowired
private Comment secondComment;
Qualifier:
Value
@Value :用于注入普通类型.
@Autowired :自动装配:
* 默认按类型进行装配.
* 按名称注入:
* @Qualifier:强制使用名称注入.
@Resource相当于:
* @Autowired和@Qualifier一起使用
@PostConstruct :相当于init-method
@PreDestroy :相当于destroy-method
三、AOP
1、相关理论
AOP(aspect oriented programming)面向切面编程,运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。spring里面的AOP是通过动态代理模式在不改变原有对象的前提下增强对象相关功能。
2、jdk动态代理
public class DynamicProxyDemo {
public static void main(String[] args) {
Subject target = new RealSubject();
ProxySubject handle = new ProxySubject(target);
Subject targetProxy = (Subject) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handle);
targetProxy.request();
}
}
//抽象角色(动态代理只能代理接口)
interface Subject {
public void request();
}
//真实角色:实现了Subject的request()方法
class RealSubject implements Subject {
public void request() {
System.out.println("From real subject.");
}
}
//动态代理类 实现了InvocationHandler
class ProxySubject implements InvocationHandler {
private Object obj;
ProxySubject(Object target){
this.obj = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before calling " + method);
method.invoke(obj, args);
System.out.println("after calling " + method);
return null;
}
}
3、通过Aspectj注解实现AOP操作
(1)引入相关jar包
spring-aop ,spring-aspects, spring-expression, com.springsource.net.sf.cglib, com.springsource.org.aopalliance, com.springsource.org.aspectj.weaver
(2)配置文件中开启注解扫描,开启aspectj 自动生成代理配置
xml方式:<context:component-scan base-package="packagePath"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
注解方式:
@Configuration
@ComponentScan(basePackages = {"com.jing.spring5"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class Config {
}
(3)编写相关类文件(被增强类和增强类)加上相应注解
(4)使用
@Test
public void aspectTestAnno(){
//ApplicationContext context = new ClassPathXmlApplicationContext("aop.xml");//通过xml配置开启
ApplicationContext context = new AnnotationConfigApplicationContext(ConfigAop.class);//通过注解开启
UserDaoImpl user = context.getBean("userDaoImpl", UserDaoImpl.class);
Object res = user.add(1,2); //user 的add方法已被增强
System.out.println(res);
}
4、相关注解及关键字说明
https://www.cnblogs.com/happy2333/p/12936182.html
(1)切面类 @Aspect: 定义切面类,加上@Aspect、@Component注解;//下文有展示
(2)切点 @Pointcut:
// 指定切面方法
@Pointcut("execution(public * com.rest.module..*.*(..))")
public void getMethods() {
}
注:execution表达式第一个*表示匹配任意的方法返回值,..(两个点)表示零个或多个,第一个..表示module包及其子包,第二个*表示所有类, 第三个*表示所有方法,第二个..表示方法的任意参数个数
// 指定注解
@Pointcut("@annotation(com.rest.utils.SysPlatLog)")
public void withAnnotationMethods() {
}
(3)Advice,在切入点上执行的增强处理,主要有五个注解:
@Before 在切点方法之前执行
@After 在切点方法之后执行
@AfterReturning 切点方法返回后执行
@AfterThrowing 切点方法抛异常执行
@Around 属于环绕增强,能控制切点执行前,执行后
(4)JoinPoint :方法中的参数JoinPoint为连接点对象,它可以获取当前切入的方法的参数、代理类等信息,因此可以记录一些信息,验证一些信息等;
(5)使用&&、||、!、三种运算符来组合切点表达式,表示与或非的关系;
(6)@annotation(annotationType) 匹配指定注解为切入点的方法;
(7)//aop代理对象
Object aThis = joinPoint.getThis();
//被代理对象
Object target = joinPoint.getTarget();
(8)调用切面注解:
@SysPlatLog(operateName = "查看详情",logNote = "查看详情")
@SneakyThrows
public Result getItem(@RequestParam(required = false) String bs){
}
四、JdbcTemplate使用步骤
spring对JDBC进行封装,使用JdbcTemplate进行数据库操作
1、导入相关jar包 druid-1.1.9(数据库连接包) mysql-connector-java-5.1.7-bin
2、配置datasource
<context:component-scan base-package="com.jing.spring5"> </context:component-scan>
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="jdbc:mysql://127.0.0.1/test"></property>
<property name="username" value="root"></property>
<property name="password" value="123456 "></property>
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
</bean>
<!-- JdbcTemplate对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
3、编写相关类
entity实体类book(id,name……)
dao类,包括接口和实现类,类中注入jdbcTemplate,在dao层进行数据库增删改查
service类,注入dao类
4、调用service
5、jdbcTemplate增删改查
@Repository
public class BookDaoImpl implements BookDao{
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void add(Book book) {
String sql = "INSERT INTO book (`name`,`newName`) VALUE (?, ?)";
Object[] args= {book.getName(),book.getNewName()};
int update = jdbcTemplate.update(sql, args);
System.out.println(update);
}
@Override
public void addBooks(List<Object[]> books) {
// List<Object[]> books = new ArrayList<>();
// Object[] b1={"book3", "book3"};
// Object[] b2={"book4", "book4"};
// books.add(b1);
// books.add(b2);
String sql = "INSERT INTO book (`name`,`newName`) VALUES (?, ?)";
int[] ints = jdbcTemplate.batchUpdate(sql, books);
System.out.println(Arrays.toString(ints));
}
@Override
public void update(Book book) {
// Book book = new Book();
// book.setName("book1");
// book.setNewName("book1111");
// book.setId(1);
String sql = "UPDATE book SET `name` = ?, `newName` = ? WHERE `id` = ?";
Object[] args= {book.getName(),book.getNewName(),book.getId()};
int update = jdbcTemplate.update(sql, args);
System.out.println(update);
}
@Override
public void updateBooks(List<Object[]> books) {
// List<Object[]> books = new ArrayList<>();
// Object[] b1={"book3", "book33", 9};
// Object[] b2={"book4", "book44", 10};
// books.add(b1);
// books.add(b2);
String sql = "UPDATE book SET `name` = ?, `newName` = ? WHERE `id` = ?";
int[] ints = jdbcTemplate.batchUpdate(sql, books);
System.out.println(Arrays.toString(ints));
}
@Override
public void delete(Integer id) {
String sql = "DELETE FROM book WHERE `id` = ?";
int update = jdbcTemplate.update(sql, id);
System.out.println(update);
}
@Override
public void deleteBooks(List<Object[]> ids) {
// List<Object[]> ids= new ArrayList<>();
// ids.add(new Object[]{3});
// ids.add(new Object[]{4});
String sql = "DELETE FROM book WHERE `id` = ?";
int[] ints = jdbcTemplate.batchUpdate(sql, ids);
jdbcTemplate.batchUpdate(sql, ids);
}
@Override
public int count() {
String sql = "SELECT COUNT(*) FROM book";
Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
return count;
}
@Override
public Book getBook(Integer id) {
String sql = "SELECT * FROM book WHERE id=?";
Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id);
return book;
}
@Override
public List<Book> getBooks(List<Integer> ids) {
String sql = "SELECT * FROM book WHERE id IN ? ";
List<Book> books = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class), ids);
return books;
}
public List<Book> getAllBooks() {
String sql = "SELECT * FROM book ";
List<Book> books = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class));
return books;
}
}
五、事务stransaction
1、引入jar包 spring-tx
2、配置启用transaction
<!-- 组件扫描 -->
<context:component-scan base-package="com.jing.spring5"></context:component-scan>
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="jdbc:mysql://127.0.0.1/ test"></property>
<property name="username" value="root"></property>
<property name="password" value="123456 "></property>
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
</bean>
<!-- JdbcTemplate对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
3、相关逻辑类:如转账业务Entity(Account包含用户名和金额)
public void transfer(){
accountDao.reduce();
int exception = 100/0;//此处抛出异常
accountDao.increase();
}
4、应用
ApplicationContext context = new ClassPathXmlApplicationContext("transaction.xml");
AccountService accountService = context.getBean("accountService", AccountService.class);
accountService.transfer();
六webFlux
1、创建springBoot项目
2引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>