AOP(面向切面编程)

特点:不通过修改源代码的方式添加新功能(这个详细可以去百度)
1.AOP(底层原理)
AOP底层使用动态代理:一般有两种:
一种是有接口(使用JDK动态代理),另一种是没有接口(使用CGLIB动态代理)
有接口的我们是通过:创建接口实现类代理对象,增强方法
没有接口的我们是通过:创建代理类子类的代理对象,增强方法

JDK动态代理

1.使用JDK动态代理,使用proxy类里面方法创建代理类对象(newProxyInstance),这个方法返回指定接口的代理类的实列 ,该方法将方法调用分派给指定的调用处理程序

newProxyInstance(classLoader loader,类<?> interfaces,InvocationHandler h)
这个方法有三个参数
第一个参数:类加载器
第二个参数:增强方法所在类,这个类实现的接口,支持多个接口
第三个参数:这个参数是一个对象而这个对象需要去实现一个InvocationHandler接口,
InvocationHandler接口里面有一个invoke()方法
invoke(Object proxy, Method method, Object[] args)方法有三个参数:
第一个是:代理对象
第二个是:当前方法
第三个是:当前参数
method.invoke( 对象,参数);执行方法
我们先来测试一下 用法:
准备工作:
1.创建一个dao包在包中写Userdao.java接口和UserdaoImpl.java去实现这个接口
2.在创建一个proxy包在包中写JDKproxy.java实习(newProxyInstance)通过这个方法我们来增强UserdaoImpl.java类

在Userdao.java接口中写两个方法add()和zhi()两个方法

package com.xiaoran.spring.dao;public interface Userdao {public int add(int a, int b);public String zhi(String t);}

在UserdaoImpl.java中写

package com.xiaoran.spring.dao;public class UserdaoImpl implements Userdao {public int add(int a, int b){return a+b;}public String zhi(String a){return a;}
}

创建JDKproxy.java在类中写

package com.xiaoran.spring.proxy;import com.xiaoran.spring.dao.Userdao;
import com.xiaoran.spring.dao.UserdaoImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;public class JDKproxy {public static void main(String args[]) {//创建接口实现类代理对象Class[] interfac = {Userdao.class};UserdaoImpl userdao=new UserdaoImpl();Userdao userdao1=(Userdao) Proxy.newProxyInstance(JDKproxy.class.getClassLoader(), interfac, new invocationHandler(userdao));userdao1.add(1,2);}
}
class invocationHandler implements InvocationHandler {//把创建的是谁的代理对象,把谁传递过来//有参构造private Object obj;public invocationHandler(Object obj) {this.obj = obj;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("方法之前执行:" + method.getName() + "传递的参数:" + Arrays.toString(args));Object res=method.invoke(obj,args);System.out.println("方法之后执行");return res;}}


最后执行的结果为:

springAOP中的 术语

  1. 连接点:类里面哪些方法可以被增强,这些方法称为连接点。
  2. 切入点:实际被真正增强的方法,称为切入点
  3. 通知:实际增强的逻辑部分我们就称为通知
  4. 切面:把通知应用到切入点的过程

ASPectJ

spring框架中一般都是基于ASPectJ实现AOP操作
ASPectJ实现AOP操作:
1.基于xml配置文件实现
2.基于注解方式实现(使用多一些)

准被工作我们需要引入AOP依赖:直接把这个 lib包添加进去
切入点表达式::
语法结构:execution([权限修饰符][返回值类型][类全路径]方法名称)

列子1:对com.xiaoran.spring.dao.BookDao 中的add增强

* 表示所有
execution(* com.xiaoran.spring.dao.BookDao.add(..))

Aop操作Aspect注解

1.创建一个类User.java
2,创建一个增强类Userproxy.java
(1)在增强类中创建方法,让不同的方法代表不同的通知类型
3.进行通知配置
(1)在spring.xml中开启注解扫描
(2)使用注解创建以上两个类
(3)在增强类上面添加注解@Aspect 这个注解的意思是:这个类生成一个你的代理对象
(4)在spring配置文件中开启生成代理对象
接下来我们就来实现一下:
1.我们新创建一个User.java在里面写一个add()方法,我们直接使用注解@component的方式创建对象
就不用在bean中写了

package com.xiaoran.spring.aspectAnno;import org.springframework.stereotype.Component;@Component
public class User{public void add(){System.out.println("add...。。方法执行");}
}

2.创建一个Userproxy.java在这里面写我们增强的方法,
用一个注解@component//创建对象
用一个注解@Aspect//开启代理生成对像
在增强类里面,在作为通知方法上面添加通知类注解,使用切入点表达式配置
通知类注解有5种:

  1. @Before 前置通知
  2. @After 在方法执行之后通知
  3. @AfterThrowing 异常通知
  4. @Around 环绕通知
  5. @AfterReturning 方法返回结果之后通知
    在引入注解里面的格式就是
    @Before(value=“”)value中写的就是我们针对哪个类里面的哪个方法增强
package com.xiaoran.spring.aspectAnno;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Component
@Aspect//开启代理生成对象
public class Userproxy {@Before(value = "execution(* com.xiaoran.spring.aspectAnno.User.add(..))")public void before(){System.out.println("前置通知。。。。。。");}}

3.我们在spring.xml中配置:
我们需要去引入context
打开扫描,在配置文件中开启生成代理对象

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "><!--配置扫描--><context:component-scan base-package="com.xiaoran.spring"></context:component-scan><!--配置文件中开启生成代理对象--><aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

4.最后写一个测试类来查看一下结果

package com.xiaoran.spring.testdemo;import com.xiaoran.spring.aspectAnno.User;
import com.xiaoran.spring.config.Configxml;
import com.xiaoran.spring.xmlbook.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class testproxy {@Testpublic void test1(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");User user =context.getBean("user",User.class);user.add();}}

我们的得到的结果是

注意其他5种方法的执行过程都是一样的,只有一种注解用法有点不同(@Around)环绕注解
环绕注解我们在使用过程中:我的增强类方法中是需要引入一个(ProceedingJoinPoint)参数用它里面的方法(proceed)来调用我们被增强的方法

  @Around(value = "execution(* com.xiaoran.spring.aspectAnno.User.add(..))")public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("环绕之前执行/......");//被增强方法执行proceedingJoinPoint.proceed();System.out.println("环绕之后执行");}

其他的不需要改变我们来查看一下结果

我还是把所有的注解都实现一下把,大家可以看一下,在Userproxy.java中写

package com.xiaoran.spring.aspectAnno;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Component
@Aspect//开启代理生成对象
public class Userproxy {@Before(value = "execution(* com.xiaoran.spring.aspectAnno.User.add(..))")public void before(){System.out.println("前置通知。。。。。。");}@After(value = "execution(* com.xiaoran.spring.aspectAnno.User.add(..))")public void after(){System.out.println("在方法执行之后执行。。。。。。");}@AfterThrowing(value = "execution(* com.xiaoran.spring.aspectAnno.User.add(..))")public void Theowing(){System.out.println("异常通知。。。。。。");}@AfterReturning(value = "execution(* com.xiaoran.spring.aspectAnno.User.add(..))")public void Runturn(){System.out.println("方法返回结果后通知。。。。。。");}@Around(value = "execution(* com.xiaoran.spring.aspectAnno.User.add(..))")public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("环绕之前执行/......");//被增强方法执行proceedingJoinPoint.proceed();System.out.println("环绕之后执行");}}

注意了注意了,接下来就又是细节操作了
1.如果有两个类都对一个方法做增强,那么我们可以设置一下增强类的优先级
(1)在增强类上面添加注解@order(数字类型值)这里值越小优先级越高

AOP操作(AspectJ在spring.xml中配置通知)

1.创建两个类
2.spring中创建两个类对像book.java和Mybook.java
3.在spring中配置文件的切入点

1.创建book.java类在类中写一个add()方法

package com.xiaoran.spring.xmlbook;
public class Book {public void add(){System.out.println("这个是adddxxxxxx。。。。。。。。。。");}
}

创建Mybook.java在类中写:我们的增强类(buy())

package com.xiaoran.spring.xmlbook;
public class Mybook {public void buy(){System.out.println("这是我们增强的方法");}
}

2.在spring中怕配置:
(1)先用bean标签创建我们的两个对象

  <bean id="book" class="com.xiaoran.spring.xmlbook.Book"></bean><bean id="mybook" class="com.xiaoran.spring.xmlbook.Mybook"></bean>

(2)配置aop增强

<!--配置aop增强--><aop:config><!--切入点id是自己设置,后写的是给哪个类,增强哪个方法--><aop:pointcut id="p" expression="execution(* com.xiaoran.spring.xmlbook.Book.add(..))"/><!--配置切面:这个就是配置我们去增强别人的类 --><aop:aspect ref="mybook![请添加图片描述](https://img-blog.csdnimg.cn/58b528df524e45d0bc20dca1f99ab06c.jpg?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP5YaJMQ==,size_20,color_FFFFFF,t_70,g_se,x_16)
"><!--增强作用在具体的方法上面:method:写的是我们的增强类中的方法名字(增强方法)  pointcut-ref:这   个是引入我们的切入点--><aop:before method="buy" pointcut-ref="p"></aop:before></aop:aspect></aop:config>


3.写一个测试类:

  @Testpublic void test2(){ApplicationContext context=new ClassPathXmlApplicationContext("spring2.xml");Book user =context.getBean("book",Book.class);user.add();}

之后的结果为:

纯注解开发

1.纯注解开法就是不需要spring.xml,我们就以上面为实列写修改一下来说明
创建一个Configxml.java来替代我们之前写的spring.xml
在这个类中写:@ComponentScan(basePackages = {“com.xiaoran.spring”}),这个就是我们的配置扫描
@EnableAspectJAutoProxy(proxyTargetClass = true)//开启Aspect成为代理对象

package com.xiaoran.spring.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
//配置扫描
@ComponentScan(basePackages = {"com.xiaoran.spring"})
//开启Aspect成为代理对象
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class Configxml {}

在book.java中添加注解@Component

package com.xiaoran.spring.xmlbook;import org.springframework.stereotype.Component;@Component
public class Book {public void add(){System.out.println("这个是adddxxxxxx。。。。。。。。。。");}
}

在Mybook.java中添加注解

package com.xiaoran.spring.xmlbook;import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;@Component
@Aspect//开启代理对象
public class Mybook {@After(value = "execution(* com.xiaoran.spring.xmlbook.Book.add(..))")public void buy(){System.out.println("这是我们增强的方法");}
}

测试类中其他地方不需要去改变,我们只需要去改变测试类中的代码把获取spring.xml的地方改为获取Configxml.class类

@Testpublic void test3(){ApplicationContext context=new AnnotationConfigApplicationContext(Configxml.class);Book user =context.getBean("book",Book.class);user.add();}

最后的结果为:

JdbcTemplate

1什么jdbcTemplate:spring框架对jdbc进行封装,使用jdbcTemplate方便实现对数据库的操作
2.准备工作:
(1)引入依赖:mysql连接数据库的jar包

只需要这5个包但是你也可以全部引入,包去哪找这个问题很重要,传送门
2.在spring.xml中配置mysql数据库连接池,每个人的密码和名字不同,我这里使用的是我的test库

 <!--配置数据库连接池--><bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/test"></property><property name="username" value="root"></property><property name="password" value="mysql123456"></property></bean>

3.在spring.xml中配置jdbcTemplate对象,注入DataSource,注意注意这里我们是用set注入大家可以看源码

 <!--配置jdbcTemplate对象,注入DataSource--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!--在这里面我们需要用set注入我们的数据库连接池--><property name="dataSource" ref="datasource"></property></bean>

4.创建service类和dao类
(1)在配置文件中还要记得打开扫描

 <!--配置扫描 --><context:component-scan base-package="com.xiaoran.spring"></context:component-scan>
(2)在service类中注入dao
(3)在dao中注入 JdbcTemplate

5.在mysql中创建一个非常简单的 表test1
在mysql中写

create table test1(id int,name char(12),age int
)

我们的准备工作就完成了

用JdbcTemplate对数据库进行添加操作

我们在创建一个entity包,创建对应我们数据库中的实体
添加一个get和set 和tostring方法

package com.xiaoran.spring.entity;public class Book {private int id;private String  name;private  int  age;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Book{" +"id=" + id +", name='" + name + '\'' +", age=" + age +'}';}
}

2.我们在service类中创建一个类BookService.java
我们在类中注入dao类
通过Bookservice类去调用我们的添加方法()


@Component
public class BookService {@Autowired//注入dao类private BookDao bookDao;//添加的方法public void add(Book book){bookDao.add(book);}}

3.在dao中创建一个BookDao.java接口和BookDaoImple.java来实现接口
BookDao.java

public interface BookDao {public void add(Book book);
}

在BookDaoImpl.java中写:
在这里就要重点说一下了注意了哟,
我们在这里引入JdbcTemplate 我们使用它里面的一个方法 update(参数1,参数2[ ])
参数1:是我们写的sql语句
参数2:是我们sql语句中问号表示的值,因为有 时我们的问号有多个,所以这是一个数组类

@Component
public class BookdaoImpl implements BookDao {@Autowiredprivate JdbcTemplate jdbcTemplate;@Overridepublic  void add(Book book){String sql="insert into test1 values (?,?,?)";Object[] args={book.getId(),book.getName(),book.getAge()};int update=jdbcTemplate.update(sql,args);System.out.println(update);//这里我们输出一下影响的行数}}

4.最后我们在写一个测试类:这里我们添加的是一个对像所以我们需要创建一个book对象用set放值,后面我们在BookDaoImpl.java中用get方法取出值

   @Testpublic void Test(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);Book book=new Book();book.setId(1);book.setName("小冉好帅");book.setAge(20);bookService.add(book);}

最后我们需要在mysql中查看一下结果

select * from  test1


我们简简单单总结一下主要就时我们要记住JdbcTemplate中的这个update()方法的使用;

用JdbcTemplate对数据库进行修改操作

这个和上面没有什么区别,主要区别就是sql语句不同
在BookService中添加一个方法

   //修改的方法public void updatebook(Book book){bookDao.updatebook(book);}

在BookDao.java中添加一个方法

 public void updatebook(Book book);

在BookdaoImpl.java中添加一个实现方法

 @Overridepublic void updatebook(Book book){String sql="update test1 set name=?,age=? where id=?";Object[] args={book.getName(),book.getAge(),book.getId()};int update=jdbcTemplate.update(sql,args);System.out.println(update);}

最后我们写一个测试类:

  @Testpublic void test2(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);Book book=new Book();book.setName("小芳");book.setAge(20);book.setId(1);bookService.updatebook(book);}

结果显示:

用JdbcTemplate对数据库进行删除操作

这个和上面没有什么区别,主要区别就是sql语句不同,还有就是我们删除是按照id删除
在BookService中添加一个方法

    //删除的方法public void deletebook(int  i){bookDao.deletebook(i);}

在BookDao.java中添加一个方法

public void deletebook(int i);

在BookdaoImpl.java中添加一个实现方法

  @Overridepublic  void deletebook(int i){String sql="delete from test1 where id=?";int update=jdbcTemplate.update(sql,i);System.out.println(update);}

最后我们写一个测试类:

  @Testpublic void test3(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);int i=1;bookService.deletebook(i);}

结果显示:最后全部没有了

查询返回某个值

我们这里的列子是去查看数据库中有几个值count

在BookService中添加一个方法

  //返回查询某个对象public  Book selectbook(int i){Book book=bookDao.seletbook(i);return book;}

在BookDao.java中添加一个方法

 public int  selectint();

在BookdaoImpl.java中添加一个实现方法:在这里面我们要实现JdbcTemplate里面的
queryForObject(第一个参数,第二参数)方法,返回某个值
第一个参数是:sql语句
第二个参数是:class< T > requiredType 返回类型的class,返回的是什么类型就写什么类型

  @Overridepublic int selectint(){String sql="select count(*) from test1";Integer integer=jdbcTemplate.queryForObject(sql,Integer.class);return integer;}

最后我们写一个测试类:

  @Testpublic void test3(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);int i=1;bookService.deletebook(i);}

结果显示:

查询返回对象用JdbcTemplate

在BookService中添加一个方法

  //返回查询某个对象public  Book selectbook(int i){Book book=bookDao.seletbook(i);return book;}

在BookDao.java中添加一个方法

 public Book  seletbook(int i);

在BookdaoImpl.java中添加一个实现方法:在这里面我们要实现JdbcTemplate里面的
queryForObject(第一个参数,第二参数第三个参数)方法,查询返回对象
第一个参数是:sql语句
第二个参数是:RowMapper接口,返回不同类型,使用这个接口里面的实现类完成数据
new BeanPropertyRowMapper<这里面写的是我们返回对象的名字>(返回对象.class)
第三个参数是:问号中的值

 @Overridepublic Book seletbook(int i){String sql="select * from test1 where id=?";Book book=jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<Book>(Book.class),i);return book;}

最后我们写一个测试类:

  @Testpublic void test5(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);int id=1;Book book=bookService.selectbook(id);System.out.println(book);}

结果显示:

查询返回列表

在BookService中添加一个方法

  //查询返回列表public List<Book> select(){List<Book> books=bookDao.select();return books;}

在BookDao.java中添加一个方法

  public List<Book> select();

在BookdaoImpl.java中添加一个实现方法:在这里面我们要实现JdbcTemplate里面的
query(第一个参数,第二个参数),查询返回列表
第一个参数是:sql语句
第二个参数是:RowMapper接口,返回不同类型,使用这个接口里面的实现类完成数据
new BeanPropertyRowMapper<这里面写的是我们返回对象的名字>(返回对象.class)

  @Overridepublic List<Book> select(){String sql="select * from test1";List<Book> list=jdbcTemplate.query(sql,new BeanPropertyRowMapper<Book>(Book.class));return list;}

最后我们写一个测试类:

     @Testpublic void test6(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);List<Book> list=bookService.select();System.out.println(list);}

结果显示:

JdbcTemplate操作数据库实现批量操作 添加

在BookService中添加一个方法

   //实现对返回列表的批量处理public void addall(List<Object[]> bat){bookDao.addall(bat);}

在BookDao.java中添加一个方法

  public void addall(List<Object[]> bat);

在BookdaoImpl.java中添加一个实现方法:在这里面我们要实现JdbcTemplate里面的
batchUpdate(第一个参数,第二个参数),查询返回列表
第一个参数是:sql语句
第二个参数是:List<Object[]> batchArgs 这是一个集合放的是我们?的值,这里面可以放很多组

   @Overridepublic void addall(List<Object[]> bat){String sql="insert into test1 values(?,?,?)";//调用batchupdate(sql,这是一个集合放的是我们?的值,这里面可以放很多组)int[] ints=jdbcTemplate.batchUpdate(sql,bat);System.out.println(Arrays.toString(ints));}

最后我们写一个测试类:

   @Testpublic void test7(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);//创建一个 列表 用来存放我们的插入数据List<Object[]> list= new ArrayList<>();Object[] o1={3,"java",18};Object[] o2={4,"mysql",18};Object[] o3={5,"c++",20};list.add(o1);list.add(o2);list.add(o3);//调用批量处理bookService.addall(list);}

批量修改和删除和上面差不多

------------------------------------------------------------------------------------------

接下来我们就把全部补齐
在BookService中添加一个方法

  package com.xiaoran.spring.service;import com.xiaoran.spring.dao.BookDao;
import com.xiaoran.spring.entity.Book;
import org.aspectj.lang.annotation.After;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.List;//调用方法@Component
public class BookService {@Autowired//注入dao类private BookDao bookDao;//添加的方法public void add(Book book){bookDao.add(book);}//修改的方法public void updatebook(Book book){bookDao.updatebook(book);}//删除的方法public void deletebook(int  i){bookDao.deletebook(i);}//查询返回结果public int selectint(){int count=bookDao.selectint();return count;}//返回查询某个对象public  Book selectbook(int i){Book book=bookDao.seletbook(i);return book;}//查询返回列表public List<Book> select(){List<Book> books=bookDao.select();return books;}//实现对返回列表的批量处理public void addall(List<Object[]> bat){bookDao.addall(bat);}//实现对列表的批量修改public void updateall(List<Object[]> bat){bookDao.updateall(bat);}//实现对数据库的批量删除public void deleteall(List<Object[]> bat){bookDao.deleteall(bat);}}

在BookDao.java中添加一个方法

  package com.xiaoran.spring.dao;import com.xiaoran.spring.entity.Book;import java.util.List;public interface BookDao {public void add(Book book);public void deletebook(int i);public void updatebook(Book book);public int  selectint();public Book  seletbook(int i);public List<Book> select();public void addall(List<Object[]> bat);public void updateall(List<Object[]>bat);public void deleteall(List<Object[]> list);
}

在BookdaoImpl.java中:

 package com.xiaoran.spring.dao;import com.xiaoran.spring.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;import java.util.Arrays;
import java.util.List;//这里面写的对数据库的操作
@Component
public class BookdaoImpl implements BookDao {@Autowiredprivate JdbcTemplate jdbcTemplate;@Overridepublic  void add(Book book){String sql="insert into test1 values (?,?,?)";Object[] args={book.getId(),book.getName(),book.getAge()};int update=jdbcTemplate.update(sql,args);System.out.println(update);}@Overridepublic void updatebook(Book book){String sql="update test1 set name=?,age=? where id=?";Object[] args={book.getName(),book.getAge(),book.getId()};int update=jdbcTemplate.update(sql,args);System.out.println(update);}@Overridepublic  void deletebook(int i){String sql="delete from test1 where id=?";int update=jdbcTemplate.update(sql,i);System.out.println(update);}@Overridepublic int selectint(){String sql="select count(*) from test1";Integer integer=jdbcTemplate.queryForObject(sql,Integer.class);return integer;}@Overridepublic Book seletbook(int i){String sql="select * from test1 where id=?";Book book=jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<Book>(Book.class),i);return book;}@Overridepublic List<Book> select(){String sql="select * from test1";List<Book> list=jdbcTemplate.query(sql,new BeanPropertyRowMapper<Book>(Book.class));return list;}@Overridepublic void addall(List<Object[]> bat){String sql="insert into test1 values(?,?,?)";//调用batchupdate(sql,这是一个集合放的是我们?的值,这里面可以放很多组)int[] ints=jdbcTemplate.batchUpdate(sql,bat);System.out.println(Arrays.toString(ints));}@Overridepublic void updateall(List<Object[]> list){String sql="update test1 set name=?,age=? where id=?";int[] i= jdbcTemplate.batchUpdate(sql,list);System.out.println(Arrays.toString(i));}@Overridepublic void deleteall(List<Object[]> list){String sql="delete from test1 where id=?";int[] i =jdbcTemplate.batchUpdate(sql,list);System.out.println(Arrays.toString(i));}}

最后我们写一个测试类:

 package com.xiaoran.spring.testdemo;import com.xiaoran.spring.entity.Book;
import com.xiaoran.spring.service.BookService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import java.util.ArrayList;
import java.util.List;public class test {@Testpublic void Test(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);Book book=new Book();book.setId(1);book.setName("小冉好帅");book.setAge(20);bookService.add(book);}@Testpublic void test2(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);Book book=new Book();book.setName("小芳");book.setAge(20);book.setId(1);bookService.updatebook(book);}@Testpublic void test3(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);int i=1;bookService.deletebook(i);}@Testpublic void test4(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);int  i =bookService.selectint();System.out.println(i);}@Testpublic void test5(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);int id=1;Book book=bookService.selectbook(id);System.out.println(book);}@Testpublic void test6(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);List<Book> list=bookService.select();System.out.println(list);}@Testpublic void test7(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);//创建一个 列表 用来存放我们的插入数据List<Object[]> list= new ArrayList<>();Object[] o1={3,"java",18};Object[] o2={4,"mysql",18};Object[] o3={5,"c++",20};list.add(o1);list.add(o2);list.add(o3);//调用批量处理bookService.addall(list);}@Testpublic void test8(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);//创建一个 列表 用来存放我们的插入数据List<Object[]> list= new ArrayList<>();Object[] o1={"java 小冉帅",18,3};Object[] o2={"mysql 小冉帅",18,4};Object[] o3={"c++ 小冉帅",20,5};list.add(o1);list.add(o2);list.add(o3);//调用批量处理bookService.updateall(list);}@Testpublic void test9(){ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");BookService bookService=context.getBean("bookService",BookService.class);//创建一个 列表 用来存放我们的插入数据List<Object[]> list= new ArrayList<>();Object[] o1={3};Object[] o2={4};Object[] o3={5};list.add(o1);list.add(o2);list.add(o3);//调用批量处理bookService.deleteall(list);}
}

我们对数据库的操作就结束了,多练习其实不难

事务

1.什么是事务,事务是数据库操作最基本单元,逻辑上的一组操作,要么都成功,如果有一个失败那么所有操作都会失败。
2.事务的作用很广泛如:我们的银行转账,必须是一个人扣钱了一个人才可以收到钱,如果转载过程中断电了那么就会转账失败。
3.我们创建一个简单的环境来实现:转帐环境搭建
(1)创建一个service类和dao类
(2)在dao类中写两个方法,一个是addmoney方法增加钱,一个是reduceMoney方法少钱的
(3)在service类中写:创建转钱的方法(1)调用dao中的两个方法
(2)创建一个数据库我们在数据库中写一个表用来记录转帐
mysql代码:

create table account(id int,name char(12),money int
)

我们在创建的表中添加两个人小冉和小芳用来模拟他们两的交易,假设他们一开始钱都是1000

insert into account values(1,'小冉',1000)
insert into account values(2,'小芳',1000)

1.在dao中创建一个Userdao.java接口,在接口中写两个方法

package com.xiaoran.spring.dao;public interface Userdao {public void addmoney();//多钱public void reduceMoney();//少钱
}

在dao中创建一个实现上面接口的方法:
在这个方法中实现接口中的方法我们实现 " 加钱" 或者 “少钱” 的方法就是直接修改数据库中我们余额

package com.xiaoran.spring.dao;import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;@Repository
public class UserdaoImpl implements Userdao{@Autowiredprivate JdbcTemplate jdbcTemplate;//多钱public void addmoney(){String sql="update account set money=money+? where name=? ";jdbcTemplate.update(sql,100,"小冉");}//少钱public void reduceMoney(){String sql="update account set money=money-? where name=? ";jdbcTemplate.update(sql,100,"小芳");}
}

3.我们创建一个UserService.java类在类中写:

package com.xiaoran.spring.service;import com.xiaoran.spring.dao.Userdao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class Userservice {//注入dao@Autowiredprivate Userdao userdao;//转载方法public void accountmoney(){//少钱userdao.reduceMoney();//多钱userdao.addmoney();}}

4.我们需要在spring.xml中配置:配置扫描,配置数据库连接池,配置配置jdbcTemplate对象,注入DataSource

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx.xsd"><!--配置扫描 --><context:component-scan base-package="com.xiaoran.spring"></context:component-scan><!--配置数据库连接池--><bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/test"></property><property name="username" value="root"></property><property name="password" value="mysql123456"></property></bean><!--配置jdbcTemplate对象,注入DataSource--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!--在这里面我们需要用set注入我们的数据库连接池--><property name="dataSource" ref="datasource"></property></bean>
</beans>

最后我们写一个测试类:

  @Testpublic void test(){ApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");Userservice  userservice=context.getBean("userservice",Userservice.class);userservice.accountmoney();}

执行之后我们查看数据库中的结果:
在mysql中写

select * from  account;

结果显示:

事实证明我们的方法是有效的;但是这是我们所说的理想情况,在实际的过程中会有很多未知的变化,
接下来我们举个列子:
我们在UserService.java中添加一个异常,模拟我们在实际过程中出现了异常:

package com.xiaoran.spring.service;import com.xiaoran.spring.dao.Userdao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class Userservice {//注入dao@Autowiredprivate Userdao userdao;//转载方法public void accountmoney(){//少钱userdao.reduceMoney();//模拟异常int i=10/0;//多钱userdao.addmoney();}}


接下来我们在执行就会发现,发现我们的小芳钱少了,而小冉的钱也没有增加,钱去哪了呢???
我们用之前的测试方法执行一下,结果显示为

所以我们就必须得引入事务啦

引入事务

1.在spring中进行事务管理操作
(2)有两种方法:编程式事务管理(了解)和声明式事务管理(使用多)
声明式事务管理:可以分为注解实现,和xml配置实现

2.在spring中进行声明事务管理(底层使用AOP原理)

事务操作(注解声明式事务管理)

1.我们在UserService.java上面添加一个注解:@Transactional 开启事务

2.我们需要在spring.xml中配置事务管理器:DataSourceTransactionManager,这里面我们需要用set注入我们的数据库连接池

  <!--配置事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!--注入数据源--><property name="dataSource" ref="datasource"></property></bean>

2.开启事务注解,前提我们需要在顶部引入tx和aop

<!--开启事务注解--><!--transaction-manager="transactionManager" 指定我们的事务管理器--><tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>


3.接下来我们在重新测试:
我们先把mysql中的数据还原一下

update account set money=1000 where name='小芳'
update account set money=1000 where name='小冉'


最后用以前的测试方法测试一下

 @Testpublic void test(){ApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");Userservice  userservice=context.getBean("userservice",Userservice.class);userservice.accountmoney();}

在数据库中查看发现:

select * from account

测试结果为:

我们在添加了事务之后,只要有一个错误就不会提交事务

我们来看一下这个注解的用法吧:
@Transactional注解里面可以写6个值分别是

  1. Propagation :事务传播行,多事物直接或间接调用,这个过程中事务时如何管理的
    propagation.REQUIRED:如果有事务在运行,当前方法就在这个事务中运行,否则就在启动一个新事物,并在自己的事务中运行;(默认是这个)
    propagation.REQUIRED_NEW:当前的方法必须启动新事物并在它自己的事务内运行,如果有事务在运行应该将它先挂起
  2. Ioslation :事务隔离,多事物之间操作如果不设置隔离性,就会产生很多问题如:脏读,重复读,虚度
    我们可以通过设置事务的隔离级别来解决问题
    默认是:Ioslation.REDATABLEREAD(可重复读)
  3. tiemout :超时间,默认是-1没有时间限制,超过我们设置的时间就会提交,不提交就会回滚
  4. readonly :是否只读,默认为false,可以查询可以添加修改删除操作,如果把值设置为True之后只能进行查询
  5. rollbackFor:回滚,设置出现哪些异常进行事务回滚
  6. norollbackFor:不回滚,设置出现哪些异常不进行事务回滚

事务操作(基于注解实现)

1.在xml中配置
(1)配置事务管理器
(2)配置事务通知
(3)配置切入点和切面

我们在spring.xml中配置:
配置事务管理器

  <!--配置事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!--注入数据源--><property name="dataSource" ref="datasource"></property></bean>

配置事务通知

  <tx:advice id="txadvice"><!--配置事务参数--><tx:attributes><!--name=""这里写的是:指定哪种方法上面添加事务propagation="" 这里面写的是:指定事务--><tx:method name="accountmoney" propagation="REQUIRED"></tx:method></tx:attributes></tx:advice>

配置切面和切面

  <!--配置切入点和 切面--><aop:config><!--配置切入点--><aop:pointcut id="pt" expression="execution(* com.xiaoran.spring.service.Userservice.accountmoney(..))"></aop:pointcut><!--配置切面advice-ref="txadvice" 这里面写的是把我们的通知配置进来pointcut-ref="pt"引入切入点--><aop:advisor advice-ref="txadvice" pointcut-ref="pt"></aop:advisor></aop:config>


之后我们去掉在UserService.java中的注解@Transactional,执行的结果还是和之前的是一样的

完全纯注解开发

1.创建一个config包在包中创建一个Txcongifg.java类
(1)在类中添加注解@Configuration//配置类
@ComponentScan(basePackages = “com.xiaoran.spring”)//开启扫描
@EnableTransactionManagement//开启事务注解

package com.xiaoran.spring.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.sql.DataSource;@Configuration//配置类
@ComponentScan(basePackages = "com.xiaoran.spring")//开启扫描
@EnableTransactionManagement//开启事务注解
public class Txcongifg {//配置数据库连接池@Beanpublic DruidDataSource getdruidDataSource(){DruidDataSource dataSource=new DruidDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/test");dataSource.setUsername("root");dataSource.setPassword("mysql123456");return dataSource;}//配置jdbcTemplate对象,注入datasource@Beanpublic JdbcTemplate jdbctemplat(DataSource dataSource){JdbcTemplate jdbcTemplate=new JdbcTemplate();jdbcTemplate.setDataSource(dataSource);return jdbcTemplate;}//-配置事务管理器@Beanpublic DataSourceTransactionManager transactionManager(DataSource dataSource){DataSourceTransactionManager transactionManager=new DataSourceTransactionManager();transactionManager.setDataSource(dataSource);return transactionManager;}
}

之后我们写一个测试类:

package com.xiaoran.spring.Test;import com.xiaoran.spring.config.Txcongifg;
import com.xiaoran.spring.service.Userservice;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Testdemo2 {@Testpublic void test2(){ApplicationContext context =new AnnotationConfigApplicationContext(Txcongifg.class);Userservice  userservice=context.getBean("userservice",Userservice.class);userservice.accountmoney();}}

执行的结果和之前的还是一样的,大家可以去多练习一下

springAOP 学习相关推荐

  1. SpringAOP学习--SpringAOP简介及原理

    前文对AOP做了介绍,实际项目中,一般不会直接上手手动实现aop,而是使用一些高级封装的aop实现,如SpringAOP. Spring是一个广泛应用的框架,SpringAOP则是Spring提供的一 ...

  2. springAop学习笔记(二,springboot进本配置和使用)

    配置 1.引入aop jar包 2.在主类上面加@EnableAspectJAutoProxy 这里要说一句:市面上常用有两种aop实现方式第一种是springaop,第二种是AspectJ,但是原始 ...

  3. SpringAOP学习笔记(一)——目标对象和代理对象

    一.目标对象和代理对象 目标对象:在SpringAOP被增强的对象 代理对象:通过aop中对目标对象进行增强,加入代理逻辑的而产生的对象 public interface Service {void ...

  4. Java SpringAOP学习之How is beforeMethodAdvice called

    Created by Wang, Jerry, last modified on Aug 16, 2016

  5. 面向切面(AOP)之Spring接口方式 schema配置方式 aspectj注解方式

    一.初识AOP   关于AOP的学习可以参看帮助文档:spring-3.2.0.M2\docs\reference\html目录下index.html的相关章节      1.AOP:Aspect-O ...

  6. aop实现原理-动态代理CGLib代理

    那接下来的话,那咱们Spring当中,这个AOP,咱们先说概念,咱们先不写具体代码,咱们就是聊,聊Spring的AOP,Spring能帮我们干啥呢,我告诉你,Spring他作为对象的容器,Spring ...

  7. Sprin框架的学习(课时七)SpringAop的学习

    目录 2022年9月9号Sprin框架的学习(课时七)Aop项内容设计23设计模式中的静态代理模式而在SpringAop中实现的时动态代理模式 第一部分 了解Java23模式的基本概念从下面的概念去理 ...

  8. Spring--AOP知识学习

    1.引入AOPjar包文件 <!--引入AOPjar包文件--><dependency><groupId>org.springframework.boot</ ...

  9. 【学习笔记】SpringAOP的用法全解

    文章目录 Spring的AOP 一. Spring对AOP的实现包括以下3种方式 **什么是AspectJ?** 二.使用Spring的AOP 1.准备工作 2.尝试写一个简单的AOP demo 3. ...

  10. 一文带你学会基于SpringAop实现操作日志的记录

    前言 大家好,这里是经典鸡翅,今天给大家带来一篇基于SpringAop实现的操作日志记录的解决的方案.大家可能会说,切,操作日志记录这么简单的东西,老生常谈了.不! 网上的操作日志一般就是记录操作人, ...

最新文章

  1. 苹果和Siri的七年之痒:Siri的落寞之路
  2. python 服务器端_python实现服务器端
  3. Java读书笔记05 类与对象
  4. 计算机课怎样回归老师控制,职业学校计算机专业课堂回归真学习
  5. linux查域名对应的ip 系统调用,DDNS 的工作原理及其在 Linux 上的实现
  6. HDU.5909.Tree Cutting(树形DP FWT/点分治)
  7. USB 设备类协议入门【转】
  8. 栈和队列之生成窗口最大值数组
  9. 《零基础看得懂的C++入门教程 》——(6)自己动手写个函数
  10. Android 之 Window、WindowManager 与窗口管理
  11. 樱花漫地集于我心,蝶舞纷飞祈愿相随---总结 适者:survival of the fittest 适者:survival of the fittest...
  12. 48.自定义邮件模板
  13. 前程无忧岗位数据爬取+Tableau可视化分析
  14. 双操作系统安装(三)Windows及Deepin深度linux双系统安装教程
  15. matlab伴随矩阵怎么表示,怎样用Matlab求矩阵的伴随矩阵
  16. 阿里巴巴达摩院发布2019十大科技趋势:语音AI在特定领域通过图灵测试...
  17. JAVA 模拟扑克牌洗牌发牌案例
  18. QQ浏览器9 主页无法修改成功的解决办法
  19. 好嗨呦是谁_好嗨哦是什么梗
  20. 开发管理---配置管理与文档管理

热门文章

  1. 西门子SMART200 PLC和托利多电子称自由口通讯程序
  2. Java未来城市练习代码01
  3. 行波iq调制器_行波型LiNbO3电光调制器的电极优化设计
  4. 身份证、组织机构代码及营业执照号校验函数
  5. matlab2016环境变量,matlab环境变量path
  6. Linux打开wim文件,linux笔记 wim编辑器
  7. 上海市犬伤处置门诊目录(上海哪些医院可以打狂犬疫苗)
  8. python ip地址处理_Python学习笔记-IP地址处理模块Ipy
  9. 极简主义、人工智能与Readhub的产品哲学
  10. 怎么关闭火狐浏览器的百度辅助模式(无障碍服务)