• 9.3AspectJ


    1.1 介绍

     AspectJ是一个基于Java语言的AOP框架

     Spring2.0以后新增了对AspectJ切点表达式支持

     @AspectJ AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面

    新版本Spring框架,建议使用AspectJ方式来开发AOP

     主要用途:自定义开发

     切入点表达式【掌握】

    1.execution()  用于描述方法 【掌握】

    语法:execution(修饰符  返回值  包..方法名(参数) throws异常)

    修饰符,一般省略

    public 公共方法

    * 任意

    返回值,不能省略

    void 返回没有值

    String 返回值字符串

    * 任意

    包,[省略]

    com.itheima.crm 固定包

    com.itheima.crm.*.service crm包下面子包任意 (例如:com.itheima.crm.staff.service

    com.itheima.crm.. crm包下面的所有子包(含自己)

    com.itheima.crm.*.service.. crm包下面任意子包,固定目录serviceservice目录任意包

    类,[省略]

    UserServiceImpl 指定类

    *Impl Impl结尾

    User* User开头

    * 任意

    方法名,不能省略

    addUser 固定方法

    add* add开头

    *Do Do结尾

    * 任意

    (参数)

    () 无参

    (int) 一个整型

    (int ,int) 两个

    (..) 参数任意

    throws ,可省略,一般不写。

    综合1

    execution(* com.itheima.crm.*.service..*.*(..))

    综合2

    <aop:pointcut expression="execution(* com.itheima.*WithCommit.*(..)) ||

                              execution(* com.itheima.*Service.*(..))" id="myPointCut"/>

    2.within:匹配包或子包中的方法(了解)

    within(com.itheima.aop..*)

    3.this:匹配实现接口的代理对象中的方法(了解)

    this(com.itheima.aop.user.UserDAO)

    4.target:匹配实现接口的目标对象中的方法(了解)

    target(com.itheima.aop.user.UserDAO)

    5.args:匹配参数格式符合标准的方法(了解)

    args(int,int)

    6.bean(id)  对指定的bean所有的方法(了解)

    bean('userServiceId')

    1.3 AspectJ 通知类型

    laop联盟定义通知类型,具有特性接口,必须实现,从而确定方法名称。

    laspectj 通知类型,只定义类型名称。已经方法格式。

    个数:6种,知道5种,掌握1中。

    before:前置通知(应用:各种校验)

    在方法执行前执行,如果通知抛出异常,阻止方法运行

    afterReturning:后置通知(应用:常规数据处理)

    方法正常返回后执行,如果方法中抛出异常,通知无法执行

    必须在方法执行后才执行,所以可以获得方法的返回值。

    around:环绕通知(应用:十分强大,可以做任何事情)

    方法执行前后分别执行,可以阻止方法的执行

    必须手动执行目标方法

    afterThrowing:抛出异常通知(应用:包装异常信息)

    方法抛出异常后执行,如果方法没有抛出异常,无法执行

    after:最终通知(应用:清理现场)

    方法执行完毕后执行,无论方法中是否出现异常

    环绕
    
     
    
    try{
    
         //前置:before
    
        //手动执行目标方法
    
        //后置:afterRetruning
    
    } catch(){
    
        //抛出异常 afterThrowing
    
    } finally{
    
        //最终 after
    
    }

    1.1 导入jar

    l 4个:

    aop联盟规范

    spring aop 实现

    aspect 规范

    spring aspect 实现

     

    一、 基于xml

    1.目标类:接口 + 实现

    2.切面类:编写多个通知,采用aspectj 通知名称任意(方法名任意)

    3.aop编程,将通知应用到目标类

    4.测试

     切面类

    MyAspect.java
    
    
    package com.jd.proxy.aspect.xml;

    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;

    /**
    * 切面类,含有多个通知
    */
    public class MyAspect {

    public void myBefore(JoinPoint joinPoint){
    System.out.println("前置通知 : " + joinPoint.getSignature().getName());
    }

    public void myAfterReturning(JoinPoint joinPoint,Object ret){
    System.out.println("后置通知 : " + joinPoint.getSignature().getName() + " , -->" + ret);
    }

    public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
    System.out.println("前");
    //手动执行目标方法
    Object obj = joinPoint.proceed();

    System.out.println("后");
    return obj;
    }

    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
    System.out.println("抛出异常通知 : " + e.getMessage());
    }

    public void myAfter(JoinPoint joinPoint){
    System.out.println("最终通知");
    }

    }
     

    spring配置

    beans.xml

    <?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: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/aop 
                                  http://www.springframework.org/schema/aop/spring-aop.xsd">
        <!-- 1 创建目标类 -->
        <bean id="userServiceId" class="com.jd.proxy.aspect.xml.UserServiceImpl"></bean>
        <!-- 2 创建切面类(通知) -->
        <bean id="myAspectId" class="com.jd.proxy.aspect.xml.MyAspect"></bean>
        <!-- 3 aop编程 
            <aop:aspect> 将切面类 声明“切面”,从而获得通知(方法)
                ref 切面类引用
            <aop:pointcut> 声明一个切入点,所有的通知都可以使用。
                expression 切入点表达式
                id 名称,用于其它通知引用
        -->
        <aop:config>
            <aop:aspect ref="myAspectId">
                <aop:pointcut expression="execution(* com.jd.proxy.aspect.xml.UserServiceImpl.*(..))" id="myPointCut"/>
                
                <!-- 3.1 前置通知 
                    <aop:before method="" pointcut="" pointcut-ref=""/>
                        method : 通知,及方法名
                        pointcut :切入点表达式,此表达式只能当前通知使用。
                        pointcut-ref : 切入点引用,可以与其他通知共享切入点。
                    通知方法格式:public void myBefore(JoinPoint joinPoint){
                        参数1:org.aspectj.lang.JoinPoint  用于描述连接点(目标方法),获得目标方法名等
                    例如:
                <aop:before method="myBefore" pointcut-ref="myPointCut"/>
                -->
                
                <!-- 3.2后置通知  ,目标方法后执行,获得返回值
                    <aop:after-returning method="" pointcut-ref="" returning=""/>
                        returning 通知方法第二个参数的名称
                    通知方法格式:public void myAfterReturning(JoinPoint joinPoint,Object ret){
                        参数1:连接点描述
                        参数2:类型Object,参数名 returning="ret" 配置的
                    例如:
                <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" />
                -->
                
                <!-- 3.3 环绕通知 
                    <aop:around method="" pointcut-ref=""/>
                    通知方法格式:public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
                        返回值类型:Object
                        方法名:任意
                        参数:org.aspectj.lang.ProceedingJoinPoint
                        抛出异常
                    执行目标方法:Object obj = joinPoint.proceed();
                    例如:
                <aop:around method="myAround" pointcut-ref="myPointCut"/>
                -->
                <!-- 3.4 抛出异常
                    <aop:after-throwing method="" pointcut-ref="" throwing=""/>
                        throwing :通知方法的第二个参数名称
                    通知方法格式:public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
                        参数1:连接点描述对象
                        参数2:获得异常信息,类型Throwable ,参数名由throwing="e" 配置
                    例如:
                <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>
                -->
                <!-- 3.5 最终通知 -->            
                <aop:after method="myAfter" pointcut-ref="myPointCut"/>
                
                
                
            </aop:aspect>
        </aop:config>
    </beans>
    UserService.java
    package com.jd.proxy.aspect.xml;
    
    public interface UserService {
        
        public void addUser();
        public String updateUser();
        public void deleteUser();
    
    }
    UserServiceImpl.java
    package com.jd.proxy.aspect.xml;
    
    public class UserServiceImpl implements UserService {
    
        @Override
        public void addUser() {
            System.out.println("d_aspect.a_xml addUser");
        }
    
        @Override
        public String updateUser() {
            System.out.println("d_aspect.a_xml updateUser");
    //        int i = 1/ 0;
            return "阳志就是屌";
        }
    
        @Override
        public void deleteUser() {
            
            System.out.println("d_aspect.a_xml deleteUser");
        }
    
    }
    TestAspectXml.java
    package com.jd.proxy.aspect.xml;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestAspectXml {
        
        @Test
        public void demoAspect(){
            String xmlPath = "com/jd/proxy/aspect/xml/beans.xml";
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
            
            //获得目标类
            UserService userService = (UserService) applicationContext.getBean("userServiceId");
            userService.addUser();
            userService.updateUser();
            userService.deleteUser();
        }
    
    }

     

     

    二、 基于注解

    1.1.1 替换bean

    <!-- 1 创建目标类 -->
    
    <bean id="userServiceId" class="com.itheima.d_aspect.b_anno.UserServiceImpl"></bean>
    
    <!-- 2 创建切面类(通知) -->
    
    <bean id="myAspectId" class="com.itheima.d_aspect.b_anno.MyAspect"></bean>

    注意:扫描

    <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/aop
    
              http://www.springframework.org/schema/aop/spring-aop.xsd
    
              http://www.springframework.org/schema/context
    
              http://www.springframework.org/schema/context/spring-context.xsd">
    
    <!-- 1.扫描 注解类 -->
    
    <context:component-scan base-package="com.itheima.d_aspect.b_anno"></context:component-scan>

    替换aop

     必须进行aspectj 自动代理

    <!-- 2.确定 aop注解生效 -->
    
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    声明切面

    <aop:aspect ref="myAspectId">

    替换前置通知

    <aop:before method="myBefore" pointcut="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))"/>

    //切入点当前有效

    @Before("execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))")

    public void myBefore(JoinPoint joinPoint){

    System.out.println("前置通知 : " + joinPoint.getSignature().getName());

    }

    替换 公共切入点

    <aop:pointcut expression="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))" id="myPointCut"/>
    //声明公共切入点
    
    @Pointcut("execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))")
    
    private void myPointCut(){
    
    }

    替换后置

    <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" />
    @AfterReturning(value="myPointCut()" ,returning="ret")
    
    public void myAfterReturning(JoinPoint joinPoint,Object ret){
    
    System.out.println("后置通知 : " + joinPoint.getSignature().getName() + " , -->" + ret);
    
    }

    替换环绕

    <aop:around method="myAround" pointcut-ref="myPointCut"/>
    @Around(value = "myPointCut()")
    
    public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
    
    System.out.println("");
    
    //手动执行目标方法
    
    Object obj = joinPoint.proceed();
    
     
    
    System.out.println("");
    
    return obj;
    
    }

     替换抛出异常

    <aop:after-throwing method="myAfterThrowing" pointcut="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))" throwing="e"/>
    @AfterThrowing(value="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))" ,throwing="e")
    
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
    
    System.out.println("抛出异常通知 : " + e.getMessage());
    
    }

     

    整体代码

    UserServiceImpl.java
    package com.jd.proxy.aspect.anno;
    
    import org.springframework.stereotype.Service;
    
    @Service("userServiceId")
    public class UserServiceImpl implements UserService {
    
        @Override
        public void addUser() {
            System.out.println("d_aspect.b_anno addUser");
        }
    
        @Override
        public String updateUser() {
            System.out.println("d_aspect.b_anno updateUser");
            int i = 1/ 0;
            return "阳志就是屌";
        }
    
        @Override
        public void deleteUser() {
            
            System.out.println("d_aspect.b_anno deleteUser");
        }
    
    }
    UserService.java
    package com.jd.proxy.aspect.anno;
    
    public interface UserService {
        
        public void addUser();
        public String updateUser();
        public void deleteUser();
    
    }
    MyAspect.java
    package com.jd.proxy.aspect.anno;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    /**
     * 切面类,含有多个通知
     */
    @Component
    @Aspect
    public class MyAspect {
        
        //切入点当前有效
    //    @Before("execution(* com.jd.proxy.aspect.anno.UserServiceImpl.*(..))")
        public void myBefore(JoinPoint joinPoint){
            System.out.println("前置通知 : " + joinPoint.getSignature().getName());
        }
        
        //声明公共切入点
        @Pointcut("execution(* com.jd.proxy.aspect.anno.UserServiceImpl.*(..))")
        private void myPointCut(){
        }
        
    //    @AfterReturning(value="myPointCut()" ,returning="ret")
        public void myAfterReturning(JoinPoint joinPoint,Object ret){
            System.out.println("后置通知 : " + joinPoint.getSignature().getName() + " , -->" + ret);
        }
        
    //    @Around(value = "myPointCut()")
        public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
            System.out.println("");
            //手动执行目标方法
            Object obj = joinPoint.proceed();
            
            System.out.println("");
            return obj;
        }
        
    //    @AfterThrowing(value="execution(* com.jd.proxy.aspect.anno.UserServiceImpl.*(..))" ,throwing="e")
        public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
            System.out.println("抛出异常通知 : " + e.getMessage());
        }
        
        @After("myPointCut()")
        public void myAfter(JoinPoint joinPoint){
            System.out.println("最终通知");
        }
    
    }

    beans.xml

    <?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/aop 
                                  http://www.springframework.org/schema/aop/spring-aop.xsd
                                  http://www.springframework.org/schema/context 
                                  http://www.springframework.org/schema/context/spring-context.xsd">
        
        <!-- 1.扫描 注解类 -->
        <context:component-scan base-package="com.jd.proxy.aspect.anno"></context:component-scan>
        
        <!-- 2.确定 aop注解生效 -->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
    </beans>
    TestAspectAnno.java
    package com.jd.proxy.aspect.anno;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestAspectAnno {
        
        @Test
        public void demoAnno(){
            String xmlPath = "com/jd/proxy/aspect/anno/beans.xml";
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
            
            //获得目标类
            UserService userService = (UserService) applicationContext.getBean("userServiceId");
            userService.addUser();
            userService.updateUser();
            userService.deleteUser();
        }
    
    }

     JdbcTemplate

    l spring 提供用于操作JDBC工具类,类似:DBUtils

    依赖 连接池DataSource (数据源)

    1.1 环境搭建

    1.1.1 创建表

    create database ee19_spring_day02;
    
    use ee19_spring_day02;
    
    create table t_user(
    
      id int primary key auto_increment,
    
      username varchar(50),
    
      password varchar(32)
    
    );
    
     
    
    insert into t_user(username,password) values('jack','1234');
    
    insert into t_user(username,password) values('rose','5678');

    1.1.2 导入jar

    1.1.3 javabean

    package com.itheima.domain;
    
     
    
    public class User {
    
     
    
    private Integer id;
    
    private String username;
    
    private String password;

    1.2 使用api(了解)

    public static void main(String[] args) {
    
     
    
    //1 创建数据源(连接池) dbcp
    
    BasicDataSource dataSource = new BasicDataSource();
    
    // * 基本4项
    
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    
    dataSource.setUrl("jdbc:mysql://localhost:3306/ee19_spring_day02");
    
    dataSource.setUsername("root");
    
    dataSource.setPassword("1234");
    
     
    
     
    
    //2  创建模板
    
    JdbcTemplate jdbcTemplate = new JdbcTemplate();
    
    jdbcTemplate.setDataSource(dataSource);
    
     
    
     
    
    //3 通过api操作
    
    jdbcTemplate.update("insert into t_user(username,password) values(?,?);", "tom","998");
    
     
    
    }

    1.3 配置DBCP

    <!-- 创建数据源 -->
    
    <bean id="dataSourceId" class="org.apache.commons.dbcp.BasicDataSource">
    
    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    
    <property name="url" value="jdbc:mysql://localhost:3306/ee19_spring_day02"></property>
    
    <property name="username" value="root"></property>
    
    <property name="password" value="1234"></property>
    
    </bean>
    
    <!-- 创建模板 ,需要注入数据源-->
    
    <bean id="jdbcTemplateId" class="org.springframework.jdbc.core.JdbcTemplate">
    
    <property name="dataSource" ref="dataSourceId"></property>
    
    </bean>
    
     
    
    <!-- 配置dao -->
    
    <bean id="userDaoId" class="com.itheima.c_dbcp.UserDao">
    
    <property name="jdbcTemplate" ref="jdbcTemplateId"></property>
    
    </bean>

    1.4 配置C3P0

    <!-- 创建数据源 c3p0-->
    
    <bean id="dataSourceId" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    
    <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ee19_spring_day02"></property>
    
    <property name="user" value="root"></property>
    
    <property name="password" value="1234"></property>
    
    </bean>

    1.5 使用JdbcDaoSupport

    1.5.1 dao

    1.5.2 spring配置文件

    <!-- 配置dao 
    
    * dao 继承 JdbcDaoSupport,之后只需要注入数据源,底层将自动创建模板
    
    -->
    
    <bean id="userDaoId" class="com.itheima.e_jdbcdaosupport.UserDao">
    
    <property name="dataSource" ref="dataSourceId"></property>
    
    </bean>

    1.5.3 源码分析

    1.6 配置properties

    1.6.1 properties文件

    jdbc.driverClass=com.mysql.jdbc.Driver
    
    jdbc.jdbcUrl=jdbc:mysql://localhost:3306/ee19_spring_day02
    
    jdbc.user=root
    
    jdbc.password=1234

    1.6.2 spring配置

    <!-- 加载配置文件
    
    "classpath:"前缀表示 src下
    
    在配置文件之后通过  ${key} 获得内容
    
    -->
    
    <context:property-placeholder location="classpath:com/itheima/f_properties/jdbcInfo.properties"/>
    
     
    
    <!-- 创建数据源 c3p0-->
    
    <bean id="dataSourceId" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    
    <property name="driverClass" value="${jdbc.driverClass}"></property>
    
    <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
    
    <property name="user" value="${jdbc.user}"></property>
    
    <property name="password"  value="${jdbc.password}"></property>
    
    </bean>

    要求

    properties +  JdbcDaoSupport  + c3p0

    UserDao  --> api ( update / query  / queryForObject)

    1.1.5 aop注解总结

    @Aspect  声明切面,修饰切面类,从而获得 通知。

    通知

    @Before 前置

    @AfterReturning 后置

    @Around 环绕

    @AfterThrowing 抛出异常

    @After 最终

    切入点

    @PointCut ,修饰方法 private void xxx(){}  

    之后通过“方法名”获得切入点引用

  • 相关阅读:
    QT::QString 很全的使用
    QString与TCHAR/wchar_t/LPWSTR之间的类型转换
    Django day24 cbv和APIView的源码分析 和 resful的规范
    Django day17 博客项目(一)
    Django day16 Auth组件
    Git 和 Redis 的基本认识
    Django day15 (二) csrf的 跨站请求伪造 与 局部禁用 , 局部使用
    Django day15 (一) cbv装饰器 , 中间件
    Django day14(二) Session
    Django基础必备三件套: HttpResponse render redirect
  • 原文地址:https://www.cnblogs.com/weihu/p/9501741.html
Copyright © 2020-2023  润新知