springAOP 学习
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中的 术语
- 连接点:类里面哪些方法可以被增强,这些方法称为连接点。
- 切入点:实际被真正增强的方法,称为切入点
- 通知:实际增强的逻辑部分我们就称为通知
- 切面:把通知应用到切入点的过程
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种:
- @Before 前置通知
- @After 在方法执行之后通知
- @AfterThrowing 异常通知
- @Around 环绕通知
- @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个值分别是
- Propagation :事务传播行,多事物直接或间接调用,这个过程中事务时如何管理的
propagation.REQUIRED:如果有事务在运行,当前方法就在这个事务中运行,否则就在启动一个新事物,并在自己的事务中运行;(默认是这个)
propagation.REQUIRED_NEW:当前的方法必须启动新事物并在它自己的事务内运行,如果有事务在运行应该将它先挂起 - Ioslation :事务隔离,多事物之间操作如果不设置隔离性,就会产生很多问题如:脏读,重复读,虚度
我们可以通过设置事务的隔离级别来解决问题
默认是:Ioslation.REDATABLEREAD(可重复读) - tiemout :超时间,默认是-1没有时间限制,超过我们设置的时间就会提交,不提交就会回滚
- readonly :是否只读,默认为false,可以查询可以添加修改删除操作,如果把值设置为True之后只能进行查询
- rollbackFor:回滚,设置出现哪些异常进行事务回滚
- 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 学习相关推荐
- SpringAOP学习--SpringAOP简介及原理
前文对AOP做了介绍,实际项目中,一般不会直接上手手动实现aop,而是使用一些高级封装的aop实现,如SpringAOP. Spring是一个广泛应用的框架,SpringAOP则是Spring提供的一 ...
- springAop学习笔记(二,springboot进本配置和使用)
配置 1.引入aop jar包 2.在主类上面加@EnableAspectJAutoProxy 这里要说一句:市面上常用有两种aop实现方式第一种是springaop,第二种是AspectJ,但是原始 ...
- SpringAOP学习笔记(一)——目标对象和代理对象
一.目标对象和代理对象 目标对象:在SpringAOP被增强的对象 代理对象:通过aop中对目标对象进行增强,加入代理逻辑的而产生的对象 public interface Service {void ...
- Java SpringAOP学习之How is beforeMethodAdvice called
Created by Wang, Jerry, last modified on Aug 16, 2016
- 面向切面(AOP)之Spring接口方式 schema配置方式 aspectj注解方式
一.初识AOP 关于AOP的学习可以参看帮助文档:spring-3.2.0.M2\docs\reference\html目录下index.html的相关章节 1.AOP:Aspect-O ...
- aop实现原理-动态代理CGLib代理
那接下来的话,那咱们Spring当中,这个AOP,咱们先说概念,咱们先不写具体代码,咱们就是聊,聊Spring的AOP,Spring能帮我们干啥呢,我告诉你,Spring他作为对象的容器,Spring ...
- Sprin框架的学习(课时七)SpringAop的学习
目录 2022年9月9号Sprin框架的学习(课时七)Aop项内容设计23设计模式中的静态代理模式而在SpringAop中实现的时动态代理模式 第一部分 了解Java23模式的基本概念从下面的概念去理 ...
- Spring--AOP知识学习
1.引入AOPjar包文件 <!--引入AOPjar包文件--><dependency><groupId>org.springframework.boot</ ...
- 【学习笔记】SpringAOP的用法全解
文章目录 Spring的AOP 一. Spring对AOP的实现包括以下3种方式 **什么是AspectJ?** 二.使用Spring的AOP 1.准备工作 2.尝试写一个简单的AOP demo 3. ...
- 一文带你学会基于SpringAop实现操作日志的记录
前言 大家好,这里是经典鸡翅,今天给大家带来一篇基于SpringAop实现的操作日志记录的解决的方案.大家可能会说,切,操作日志记录这么简单的东西,老生常谈了.不! 网上的操作日志一般就是记录操作人, ...
最新文章
- 苹果和Siri的七年之痒:Siri的落寞之路
- python 服务器端_python实现服务器端
- Java读书笔记05 类与对象
- 计算机课怎样回归老师控制,职业学校计算机专业课堂回归真学习
- linux查域名对应的ip 系统调用,DDNS 的工作原理及其在 Linux 上的实现
- HDU.5909.Tree Cutting(树形DP FWT/点分治)
- USB 设备类协议入门【转】
- 栈和队列之生成窗口最大值数组
- 《零基础看得懂的C++入门教程 》——(6)自己动手写个函数
- Android 之 Window、WindowManager 与窗口管理
- 樱花漫地集于我心,蝶舞纷飞祈愿相随---总结 适者:survival of the fittest 适者:survival of the fittest...
- 48.自定义邮件模板
- 前程无忧岗位数据爬取+Tableau可视化分析
- 双操作系统安装(三)Windows及Deepin深度linux双系统安装教程
- matlab伴随矩阵怎么表示,怎样用Matlab求矩阵的伴随矩阵
- 阿里巴巴达摩院发布2019十大科技趋势:语音AI在特定领域通过图灵测试...
- JAVA 模拟扑克牌洗牌发牌案例
- QQ浏览器9 主页无法修改成功的解决办法
- 好嗨呦是谁_好嗨哦是什么梗
- 开发管理---配置管理与文档管理
热门文章
- 西门子SMART200 PLC和托利多电子称自由口通讯程序
- Java未来城市练习代码01
- 行波iq调制器_行波型LiNbO3电光调制器的电极优化设计
- 身份证、组织机构代码及营业执照号校验函数
- matlab2016环境变量,matlab环境变量path
- Linux打开wim文件,linux笔记 wim编辑器
- 上海市犬伤处置门诊目录(上海哪些医院可以打狂犬疫苗)
- python ip地址处理_Python学习笔记-IP地址处理模块Ipy
- 极简主义、人工智能与Readhub的产品哲学
- 怎么关闭火狐浏览器的百度辅助模式(无障碍服务)