关于Spring中AOP的使用以及对数据库的连接操作

关于Spring中IOC的使用链接

(14条消息) spring boot整合shiro实现登录认证授权你_qq_59776041的博客-CSDN博客_shiro

AOP

AOP概念

  • 什么是AOP

    • 面向切面编程

    • 利用AOP可以对业务逻辑的各个方面进行隔离,从而使业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率

    • 通俗描述:不通过改源代码的方式,在主干功能里面添加新的功能

AOP的底层原理

  • AOP的底层使用动态代理

    两种动态代理

    • 有接口,使用JDK动态代理

      • 创建接口实现类代理对象,增强类的方法

    • 没有接口,使用CGLIB动态代理

      • 创建当前子类的代理对象,增强类的方法

AOP(JDK动态代理)

  1. 使用 JDK 动态代理,使用 Proxy 类里面的方法创建代理对象

    • 调用newProxyInstance

      • loader:类加载器

      • interfaces:增强方法所在的类,这个类实现的接口,支持多个接口

      • h:实现接口InvocationHandler,创建代理对象,写增强的方法

  2. JDK动态代理代码

    1. 创建接口,定义方法

      public interface UserDao {
          public int add(int a,int b);
          public String update(String id);
      }

    2. 创建接口实现类,实现方法

      public class UserDaoImpl implements UserDao{
          @Override
          public int add(int a, int b) {
              return a+b;
          }
      ​
          @Override
          public String update(String id) {
              return id;
          }
      }
  3. 使用Proxy类创建接口代理对象

    public class JDKProxy {
    ​
        public static void main(String[] args) {
            //创建接口实现类代理对象
            Class[] interfaces = {UserDao.class};
    ​
    //        Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
    //            @Override
    //            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //                return null;
    //            }
    //        });
            UserDaoImpl userDao = new UserDaoImpl();
            UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
            int add = dao.add(1, 4);
            System.out.println(add);
        }
    }
    ​
    //创建代理对象代码
    class UserDaoProxy implements InvocationHandler{
    ​
        // 1.把创建增强类传入   有参数构造传递
        private Object obj;
        public UserDaoProxy(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 invoke = method.invoke(obj, args);
            //方法之后
            System.out.println("方法之后执行..."+obj);
            return invoke;
        }
    }

AOP(术语)

  • 连接点:

    类里面哪些方法可以被增强,这些方法称为连接点

  • 切入点:

    实际被增强的方法,称为切入点

  • 通知(增强):

    • 实际增强的逻辑部分被称为通知

    • 通知有很多种类型

      • 前置通知

      • 后置通知

      • 环绕通知

      • 异常通知

      • 最终通知

  • 切面:

    把通知应用到切入点的过程(是个动作)

AOP(准备)

  1. Spring基于 AspectJ 实现 AOP 操作

    • 什么是AspectJ

      AspectJ不是 Spring 组成部分,对立 AOP 框架,一般把 Spring 和 AspectJ 一起使用,进行AOP操作

  2. 基于AspectJ实现AOP操作

    • xml配置文件

    • 注解方式

  3. 在项目工程里引入AOP相关依赖

  4. 切入点表达式

    • 切入点表达式作用:知道对哪个类哪个方法进行增强

    • 语法结构:

      execution([权限修饰符] [返回类型] [类群路径] [方法名称] ([参数列表]) )

      举例一:对com.company.UserDao类里面的add方法进行增强 execution(* com.company.UserDao.add(..))

      举例二:对com.company.BookDao类里面所有方法进行增强 execution(* com.company.BookDao.*(..))

      举例二:对com.company包里面所有类的所有方法进行增强 execution(* com.company.* . *(..))

AOP操作(注解)

  • 创建类,定义要被增强的方法

  • 创建增强类(编写增强逻辑)

    • 在增强类里面,创建方法,让不同方法代表不同通知类型

  • 进行通知的配置

    • 在Spring中开启注解扫描

      <?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.xsd
                                  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                                  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
      ​
      <!--    开启注解扫描-->
          <context:component-scan base-package="com.company.aopanno"></context:component-scan>
      </beans>
    • 使用注解创建 User 和 UserProxy 对象

    • 在增强类上面添加@Aspect

    • 在 spring 配置文件中开启生成代理对象

      <!--    开启注解扫描-->
          <context:component-scan base-package="com.company.aopanno"></context:component-scan>
      ​
      <!--    开启aspectJ生成代理的对象-->
          <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
      </beans>
    • 配置不同类型的通知

      @Aspect //生成代理对象
      @Component
      public class UserProxy {
      ​
          @Before(value = "execution(* com.company.aopanno.User.add(..))")
          public void before(){
              System.out.println("before、、、、、");
          }
      ​
          //最终通知
          @After(value = "execution(* com.company.aopanno.User.add(..))")
          public void after(){
              System.out.println("after、、、、、");
          }
      ​
          //后置通知(返回通知)
          @AfterReturning(value = "execution(* com.company.aopanno.User.add(..))")
          public void afterReturning(){
              System.out.println("AfterReturning、、、、、");
          }
      ​
          //异常通知
          @AfterThrowing(value = "execution(* com.company.aopanno.User.add(..))")
          public void afterThrowing(){
              System.out.println("AfterThrowing、、、、、");
          }
      ​
          @Around(value = "execution(* com.company.aopanno.User.add(..))")
          public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
              System.out.println("around1、、、、、");
              //被增强的方法执行
              proceedingJoinPoint.proceed();
              System.out.println("around2、、、、、");
          }
      }
      ​
    • 相同的切入点抽取

         //相同的切入点抽取
          @Pointcut(value = "execution(* com.company.aopanno.User.add(..))")
          public void pointDemo(){
          }
          @Before(value = "pointDemo()")
          public void before(){
              System.out.println("before、、、、、");
          }
  • 有多个增强类对同一个方法增强,设置增强优先级

    • 在增强类上添加@Order(数字类型值),值越小优先级越高

AOP操作(AspectJ配置文件)

  • 创建两个类增强类和被增强类,创建方法

  • 在spring配置文件中创建两个类对象

  • 在spring配置文件中配置切入点

    <?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.xsd
                                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--    创建对象-->
        <bean id="book" class="com.company.aopxml.Book"></bean>
        <bean id="bookProxy" class="com.company.aopxml.BookProxy"></bean>
    ​
    <!--    配置aop增强-->
        <aop:config>
    <!--        切入点-->
            <aop:pointcut id="p" expression="execution(* com.company.aopxml.Book.buy(..))"/>
    <!--        配置切面-->
            <aop:aspect ref="bookProxy">
    <!--            增强的具体方法-->
                <aop:before method="before" pointcut-ref="p"/>
            </aop:aspect>
        </aop:config>
    </beans>

AOP(全注解)

  • 创建配置类

    @Configuration
    @ComponentScan(basePackages = {"com.company"})
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    public class ConfigAop {
    }

JdbcTemplate

JdbcTemplate概念及使用

  • Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作

  • 引入相关 jar 包

  • 组件扫描

    <!-- 组件扫描 -->
    <context:component-scan base-package="com.aijj"></context:component-scan>

  • 在 spring 配置文件配置

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
     destroy-method="close">
     <property name="url" value="jdbc:mysql:///test" />
     <property name="username" value="root" />
     <property name="password" value="root" />
     <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    </bean>
  • 配置 JdbcTemplate 对象,注入 DataSource

    <!-- JdbcTemplate 对象 -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
     <!--注入 dataSource-->
     <property name="dataSource" ref="dataSource"></property><!--set方式注入-->
    </bean>
  • 创建 service 类,创建 dao 类,在 dao 注入 jdbcTemplate 对象

    @Service
    public class BookService {
     //注入 dao
     @Autowired
     private BookDao bookDao;
    }
    ​
    @Repository
    public class BookDaoImpl implements BookDao {
     //注入 JdbcTemplate
     @Autowired
     private JdbcTemplate jdbcTemplate;
    }

JdbcTemplate 操作数据库

  • 对应实体类、dao层和service层

  • 在dao层进行数据库的操作

    • 调用 JdbcTemplate 对象里面 update 方法实现添加操作

      @Repository
      public class BookDaoImpl implements BookDao {
       //注入 JdbcTemplate
       @Autowired
       private JdbcTemplate jdbcTemplate;
       //添加的方法
       @Override
       public void add(Book book) {
       //1 创建 sql 语句
       String sql = "insert into t_book values(?,?,?)";
       //2 调用方法实现
       Object[] args = {book.getUserId(), book.getUsername(),book.getUstatus()};
       int update = jdbcTemplate.update(sql,args);
       System.out.println(update);
       }
      }
    • 修改和删除也是调用update方法

      //1、修改
      @Override
      public void updateBook(Book book) {
       String sql = "update t_book set username=?,ustatus=? where user_id=?";
       Object[] args = {book.getUsername(), book.getUstatus(),book.getUserId()};
       int update = jdbcTemplate.update(sql, args);
       System.out.println(update);
      }
      //2、删除
      @Override
      public void delete(String id) {
       String sql = "delete from t_book where user_id=?";
       int update = jdbcTemplate.update(sql, id);
       System.out.println(update);
      }
      //使用JdbcTemplate 模板所实现的 “增删改” 都是调用了同一个 “update” 方法
      ​
    • 查询操作

      • 返回某些值~~~调用queryForObject方法

        //查询表记录数
        @Override
        public int selectCount() {
         String sql = "select count(*) from t_book";
        //queryForObject方法中:第一个参数代表--sql语句;第二个参数代表--返回类型class  
         Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
         return count;
        }
      • 返回对象值~~~调用queryForObject方法

        //查询返回对象
        @Override
        public Book findBookInfo(String id) {
         String sql = "select * from t_book where user_id=?";
         //调用方法
        /*
            queryForObject方法中:
                第一个参数:sql语句
                第二个参数:RowMapper 是接口,针对返回不同类型数据,使用这个接口里面 实现类 完成数据封装
                第三个参数:sql 语句值
        */
         Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id);
         return book;
        }
      • 查询返回集合~~~调用query函数

        //所用场景:查询图书列表分页、、
        //查询返回集合
        @Override
        public List<Book> findAllBook() {
         String sql = "select * from t_book";
         //调用方法
         List<Book> bookList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class));
         return bookList;
        }
        ​
      • 批量操作数据库~~~调用batchupdate函数

        //批量添加
        @Override
        public void batchAddBook(List<Object[]> batchArgs) {
         String sql = "insert into t_book values(?,?,?)";
        //batchUpdate方法 第一个参数:sql语句     第二个参数:List集合,添加多条记录数据
         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);
        ​
      • 批量修改数据库~~~调用batchupdate函数

        //批量修改(同批量添加一样,调用同一个方法)
        @Override
        public void batchUpdateBook(List<Object[]> batchArgs) {
         String sql = "update t_book set username=?,ustatus=? where user_id=?";
         int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
         System.out.println(Arrays.toString(ints));
        }
        ​

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Spring AOPAspect注解来实现操作记录到数据库的功能。首先,需要创建一个切面使用@Aspect注解进行标记,并在该声明一个@Before注解的方法。在该方法使用JoinPoint对象来获取连接点信息,进而获取操作记录的相关信息,并将其保存到数据库。需要注意的是,操作记录的相关信息应该尽可能地详细,包括操作人员、操作时间、操作型、操作目标等。 示例代码如下: @Aspect @Component public class OperatorAspect { @Autowired private OperatorLogService operatorLogService; @Before("execution(* com.example.demo.service.*.*(..))") public void logOperator(JoinPoint joinPoint) { OperatorLog operatorLog = new OperatorLog(); operatorLog.setOperatorName("Admin"); operatorLog.setOperatorTime(LocalDateTime.now()); operatorLog.setOperatorType("Update"); operatorLog.setOperatorTarget(joinPoint.getSignature().toShortString()); operatorLogService.save(operatorLog); } } 其,JoinPoint对象提供了获取连接点信息的多种方法,如下表所示: 方法名 描述 getArgs() 获取连接点方法运行时的参数列表 getThis() 获取代理对象 getTarget() 获取目标对象 getSignature() 获取连接点的方法签名对象 toShortString() 获取连接点的方法简短签名名称 toLongString() 获取连接点的方法全限定签名名称 getKind() 获取连接型,如method-execution getSourceLocation() 获取连接点所在的位置 getStaticPart() 获取连接点所在的静态部分 需要在Spring配置文件将该切面注入到容器,并启用AOP自动代理: <context:component-scan base-package="com.example.demo"/> <aop:aspectj-autoproxy proxy-target-class="true"/>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值