(1)、AOP:面向切面编程,对业务逻辑的各个部分进行隔离,从而降低耦合度,提高程序可重用性和开发效率;将日志记录,事务处理,异常处理、性能统计,安全控制等代码从业务逻辑代码中划分出来,改变这些行为的时候不影响业务逻辑代码。
通俗描述:在不修改源代码的情况下,在主干功能里面添加新的功能。
(2)、AOP底层原理
(2.1)动态代理:
有接口,使用JDK动态代理。创建接口实现类的代理对象,增强类的方法。
JDK动态代理,使用Proxy类,java.lang.reflect.Proxy代理类。
newProxyInstance(Classloader loader, 类<?>[ ]... interfaaces,InvocationHandler h)
返回指定接口的代理类实例;
三个参数,
第一个参数,类加载器
第二个参数,增强方法所在的类,这个类实现的接口,支持多个接口,
第三个参数,实现这个接口InvocationHandler,创建代理对象,写增强方法
//(1)创建接口,定义方法
public interface UserDao{
public int add(int a,int b);
public String display(String id);
}
//(2)接口实现类
public class UserDaoImpl implements UserDao{
@override
public int add(int a,int b){
return a+b;
}
@override
public String diaplay(String id){
return id;
}
}
//(3)使用proxy类创建接口代理对象
public class JDKProxy{
//创建代理对象代码
class UserDaoProxy implements InvocationHandler{
//1、创建的谁的代理对象,把谁传进来
//有参构造
private Object obj;
public UserProxy(Object obj){
this.obj = obj;
}
//增强部分
@override
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
//方法之前执行
System.out.println("方法之前执行。。。"+method.getName()+"传递的参数"+Arrays.toString(args));
//被增强的方法执行
Object res = menthod.invoke(obj,args);
//方法之后执行
System.out.println("方法之后执行。。。"+obj);
return res;
}
}
public static void main(String[] args){
//创建接口实现类代理对象
Class[] interfaces = {UserDao.class};
UserDaoImpl userDao = new UserDaoImpl();
UserDao dao = Proxy.newProcyInstance(JDKProxy.class.getClassLoader(),interfaces,new UserProxy(userDao) );
int result = dao.add(1,3);
System.out.println(result);
}
}
无接口,使用CGLIB动态代理。创建子类的代理对象,增强类的方法。
AOP术语
连接点:类里面可以被增强的方法。
切入点:实际被增强的方法。
通知(增强):实际增加的逻辑部分。
通知有多种类型:前置通知,后置通知,环绕通知,异常通知,最终通知
切面:把通知应用到切入点的过程。
AOP操作(准备)
1、Spring 框架中一般都是基于AspectJ实现AOP操作
AspectJ,本身是单独的框架,不属于Spring组成部分,独立于AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作。
2、基于AspectJ实现AOP操作
(1)基于xml配置文件实现
(2)基于注解方式实现
3、项目里引入相关依赖
4、切入点表达式
(1)切入点表达式作用:知道对哪个类的哪个方法进行增强
(2)语法结构
execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表]))
举例1:对com.zhh.dao.BookDao类里的add进行增强
execution(* com.zhh.dao.BookDao.add(..))
举例2:对com.zhh.dao.BookDao类里的所有方法进行增强
execution(* com.zhh.dao.BookDao.*(..))
举例3:对com.zhh.dao包里的所有类,类里的所有方法进行增强
execution(* com.zhh.dao.*.*(..))
AOP操作(AspectJ注解)
1、创建类,再类里定义方法
2、
//1、创建类
@component
public class User{
public void add(){
System.out.println("add...");
}
}
//2、创建增强类(增加功能)
//增强的类
@Component
@Aspect
public class UserProxy{
//前置通知
@Before("execution(* com.zhh.annocation_aop.User.add(..))")
public void before(){
System.ouot.println("before....");
}
//返回通知,有异常不执行
@AfterReturning(value="execution(* com.zhh.annocation_aop.User.add(..))")
public void afterReturning(){
System.out.println("afterreturning...");
}
//后置通知,有没有异常都会执行
@After(value="execution(* com.zhh.annocation_aop.User.add(..))")
public void after(){
System.out.println("after...");
}
//异常通知
@AfterTrowing(value="execution(* com.zhh.annocation_aop.User.add(..))")
public void AfterTrowing(){
System.out.println("AfterTrowing...");
}
//环绕通知,之前,之后都执行
@Around(value="execution(* com.zhh.annocation_aop.User.add(..))")
public void around(ProceedingJontPoint proceedingJontPoint){
System.out.println("around...");
}
}
//3、进行通知的配置
//3.1,Spring配置文件中,开启注解扫描
<!--开启扫描-->
<context:component-scan base-package="com.zhh.annocation_aop"></context:component-scan>
//3.2,使用注解创建User和UserProxy对象@Component
//3.3,在增强类上面添加注解@Aspect
//3.4, spring配置文件中开启生成代理对象
<!--生成代理对象-->
<aop:aspectj-autoproxy> </aop:aspectj-autoproxy>
//4 配置不同的类型
//4.1 在增强类的里面,在作为通知发放上面添加通知类型注解,使用切入点表达式配置
@Before("execution(* com.zhh.annocation_aop.User.add(..))")
//5 测试类
@test
public void testAopAnno(){
ApplicationContext context = new ClassPathXmlApplicationContext("beanl.xml");
User user = context.getBean("user",User.class);
user.add();
相同接入点抽取
//抽取出来的方法
@Pointcut(value="execution(* com.zhh.spring5.aopanno.User.add(..) )")
public void pointdemo(){
}
//使用公共方法
@Before(value="pointdemo()")
public void before(){
System.out.println("before........");
}
有多个增强类对同一个方法进行增强,设置增强类的优先级,在增强类上面添加注解@Order(数字类型值),数字类型值越小优先级越高
@Component
@Aspect
@Order(1)
public class PersonProxy{
}
完全注解方式
@Configuration
@ComponentScan(basePackages={"com.zhh"})
@EnableAspectJAutoproxy(proxyTargetClass=true)
public class ConfigAop{
}
AOP操作(AspectJ配置文件)
1、创建被增强类和增强类,以及方法
2、在spring配置文件中常见两个对象
3、在spring配置文件中配置切入点
//被增强类
public class Book{
public void buy(){
System.out.println("buy.......");
}
}
//增强类
public class BookProxy{
public void before(){
System.out.println("before.......");
}
}
//创建对象
<bean id ="book" class="com.zhh.spring5.Book"></bean>
<bean id ="bookProxy" class="com.zhh.spring5.BookProxy"></bean>
<!--配置AOP的增强-->
<aop:config>
<!--切入点-->
<aop:pointcut id="p" expression="execution(* com.zhh.spring5.Book.buy(..))"/>
<!--配置切面-->
<aop:aspect ref="bookProxy">
<aop:before method="before" ponitcut-ref="p"/>
</aop:aspect>
</aop:config>
jdbcTemplate
1、什么是jdbcTemplate
(1)Spring框架对JDBC进行封装,使用jdbcTemplate方便对数据库操作
2、准备工作
(1)引入相关的jar包
2、spring配置文件中配置数据库连接池
3、配置JdbcTemplate对象,注入DataSource
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name ="url" value="jdbc:mysql:///user_db"/>
<property name="username" value="root">
<property name = "password" value="root">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<bean id="jdbcTemplate"class="org.springframe">
<property name="dataSource" ref="dataSource"></property>
</bean>
</bean>
4、创建service类,创建dao类。在dao里注入jdbcTemplate
<context:component-scan base-package ="com.zhh"></context:component-scan>
@Service
public class BookService{
@Autowired
private BookDao bookDao;
}
public interface BookDao{
}
public class BookdaoImpl implements BookDao{
@AutoWired
private JdbcTemplate jdbcTempalte;
}
jdbcTemplate 操作数据库
1、对应数据库的实体类
public class User{
private String userId;
private String userName;
private String userStates;
public void setUserId(String userId){
this.userId = userId;
}
public void setUserName(String UserName){
this.UserName = UserName;
}
public void setuserStates(String userStates){
this.userStates = userStates;
}
public String getUserId(){
return userId;
}
public String getuserName(){
return userName;
}
public String getUuserStates(){
return userStates;
}
}
2、编写service和dao
(1)、在dao进行数据库添加操作
(2)、调用JdbcTemplate对象里的update方法实现添加操作
update(String sql, Object args)有两个参数,一个是sql语句,第二个参数是可变参数,设置sql的值
@service
public class BookService{
//注入dao
@Autowired
private BookDao bookDao;
//添加的方法
public void addBook(Book book){
bookDao.add(book);
}
//修改的方法
public void updateBook(Book book){
bookDao.updateBook(book);
}
//删除的方法
public void deleteBook(String id){
bookDao.deleteBook(id);
}
}
public interface BookDao{
//添加的方法
void add(Book book);
//添加的方法
void updateBook(Book book);
//添加的方法
void delete(String id);
}
@repository
public class BookDaoImpl implements BookDao{
//注入jdbcTemplate
public JdbcTemplate jdbcTemplate;
//添加的方法
@Override
public void add(Book book){
//创建sql语句
String sql = "insert into t_book values(?,?,?)";
//创建sql语句参数
Object[] args = {book.getUserId(),book.getUserName(),book.getUserStates()};
int update = jdbcTemplate.update(sql,args);
System.out.println(update);
}
//添加的方法
@Override
public void update(Book book){
//创建sql语句
String sql = "update t_book vset userName =?,ustatus=? where user_id=?";
//创建sql语句参数
Object[] args = {book.getUserId(),book.getUserName(),book.getUserStates()};
int update = jdbcTemplate.update(sql,args);
System.out.println(update);
}
//添加的方法
@Override
public void delete(String id){
//创建sql语句
String sql = "delete from t_book where user_id=?";
//创建sql语句参数
int update = jdbcTemplate.update(sql,id);
System.out.println(update);
}
}
public class Test{
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookServoce bookservice = context.getBean("bookservice",bookService.class);
Book book = new Book();
book.setUserId("1");
book.setUserName("java");
book.setUserStatues("a");
bookService.addBook(book);
}
}
查询返回某个值
1、查询表里有多少条记录,返回某个值
2、使用iJdbcTemplate实现查询返回某个值的代码
queryForObject(String sql,Class<T> requiredType )
两个参数,第一个参数,sql语句,第二个参数,返回类型Class
@Override
public int selectCount(){
String sql = "select count(*) from t_book";
Integer count = jdbcTemplate.queryForObject(sql,Integer.class);
return count;
}
查询返回对象
1、场景:查询图书详情
2、JdbcTemplate实现查询返回对象
queryForObject(String sql, RowMapper<T> rowMapper, Object... args)
三个参数:
第一个参数,sql语句,
第二哥参数,RowMapper,是接口,返回不同类型数据,使用这个接口里面实现完成数据封装
第三个参数,sql语句值
@Override
public Book findBOOKInfo(String id){
String sql = "select * from t_book where user_id=?";
Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class),id);
return book;
}
查询返回集合
1、场景:查询图书列表分页
2、JdbcTemplate实现查询返回集合
query(String sql, RowMapper<T> rowMapper, Object... args )
三个参数:
第一个参数,sql语句,
第二哥参数,RowMapper,是接口,返回不同类型数据,使用这个接口里面实现完成数据封装
第三个参数,sql语句值
@Override
public List<Book> findAllBook(){
String sql = "select * from t_book ";
List<Book> booklist = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class));
return booklist;
}
JdbcTemplate操作数据库(批量操作)
1、批量操作:操作表里的多项记录
2、JdbcTemplate实现批量操作
batchUpdate(String sql,List<Object[]> batchArgs)\
有两个参数:
第一个参数: sql语句,
第二个参数:List集合,添加多条记录数据
@Override
public void batchAdd(List<Object[]> batchArgs){
String sql = "insert into t_book values(?,?,?)";
int[] ints = jdbcTemplate.batchUpdate(sql,batchArgs);
System.out.println(Arrays.toString(ints));
}
//批量添加测试
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"3","java","a"};
Object[] o2 = {"4","c++","b"};
Object[] o3 = {"5","mysql","c"};
batchArgs.add(o1);
batchArgs.add(o2);
batchArgs.add(o3);
bookService.batchAdd(batchArgs);
JdbcTemplate操作数据库(批量修改)
@Override
public void batchUpdateBook(List<Object[]> batchArgs){
String sql = "update t_book set username =?,where user_id=?";
int[] ints = jdbcTemplate.batchUpdate(sql,batchArgs);
System.out.println(Arrays.toString(ints));
}
//批量添加测试
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"java","a","3"};
Object[] o2 = {"c++","b","4"};
Object[] o3 = {"mysql","c","5"};
batchArgs.add(o1);
batchArgs.add(o2);
batchArgs.add(o3);
bookService.batchUpdate(batchArgs);
JdbcTemplate操作数据库(批量删除)
@Override
public void batchDeleteBook(List<Object[]> batchArgs){
String sql = "delete from t_book where user_id=?";
int[] ints = jdbcTemplate.batchUpdate(sql,batchArgs);
System.out.println(Arrays.toString(ints));
}
//批量添加测试
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"3"};
Object[] o2 = {"4"};
Object[] o3 = {"5"};
batchArgs.add(o1);
batchArgs.add(o2);
batchArgs.add(o3);
bookService.batchUDeleteBook(batchArgs);
事务概念
1、什么是事务
(1)事务是数据库操作最近本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败
(2)典型场景:银行转账
2、事物的四个特性(ACID)
(1)原子性:要么都成功。要么都失败
(2)一致性:操作之前和操作之后总量不变
(3)隔离性:多事务操作之间不会相互影响
(4)持久性:事务提交之后,表中数据发生变化保存起来