Spring03:AOP-基于Aspectj的AOP

1. Spring中的AOP简介

  • AOP(Aspect Oriented Programming)

2 代理模式

3. AOP的专业术语

  • Joinpoint(连接点):目标类中可以被增强的方法
  • Pointcut(切入点/切点):目标类中要被增强的方法
  • Advice(通知/增强):增强的代码
  1. 前置增强(通知)
  2. 后置增强(通知)
  3. 环绕增强(通知)
  • Target(目标对象):目标对象
  • Weaving(织入):把增强应用切点的过程
  • Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类
  • Aspect(切面):切点和通知的结合

4. 基于Jdk动态代理实现自定义AOP

  • pom依赖

    <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>4.3.10.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>4.3.10.RELEASE</version>
            </dependency>
    
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>4.3.10.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.8.10</version>
            </dependency>
        </dependencies>
    
  • 创建接口 UserService

    public interface UserService {
        void addUser();
        void deleteUser();
    }
    
  • 定义目标类 UserServiceImpl

    public class UserServiceImpl implements UserService {
        @Override
        public void addUser() {
            System.out.println("添加用户");
        }
    
        @Override
        public void deleteUser() {
            System.out.println("删除用户");
        }
    }
    
  • 定义切面 MyAspect

    public class MyAspect {
        public void before() {
            System.out.println("前置通知");
       	 }
        public void after() {
            System.out.println("后置通知");
        }
        public void around() {
            System.out.println("环绕通知");
        }
    }
    
  • 定义目标对象的工厂类(用于创建目标对象说对应的代理对象) UserServiceFactory

    public class UserServiceFactory {
    
        public UserService newUserServiceProxy() {
            //创建目标对象
            UserServiceImpl userService = new UserServiceImpl();
            //创建切面对象
            MyAspect myAspect = new MyAspect();
            //创建代理对象
            UserService userServiceProxy = (UserService) Proxy.newProxyInstance(UserServiceFactory.class.getClassLoader(), UserServiceImpl.class.getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    myAspect.before();
                    Object result = method.invoke(userService, args);
                    myAspect.after();
                    return result;
                }
            });
            return userServiceProxy;
        }
    }
    
  • 入口类

    public static void main(String[] args) {
        UserServiceFactory factory = new UserServiceFactory();
        UserService userService = factory.newUserServiceProxy();
        userService.addUser();
    }
    

5. AOP联盟定义的通知类型

Spring按照通知(Advice)在目标类方法的切点的位置,分为5类:

  • 前置通知org.springframework.aop.MethodBeforeAdvice
    • 在目标方法执行前实施增强
  • 后置通知org.springframework.aop.AfterReturningAdvice
    • 在目标方法执行后实施增强
  • 环绕通知org.aopalliance.intercept.MethodInterceptor
    • 在目标方法执行前后实施增强,环绕通知,必须手动执行目标方法
  • 异常抛出通知org.springframework.aop.ThrowsAdvice
  • 在方法抛出异常后实施增强
  • 引介通知 org.springframework.aop.IntroductionInterceptor
    • 在目标类中添加一些新的方法和属性

6. Spring中的AOP(不建议使用)

6.1 Spring中的半自动AOP

  • 定义接口

    public interface UserService {
        void addUser();
        void deleteUser();
    }
    
  • 定义目标类

    public class UserServiceImpl implements UserService {
        @Override
        public void addUser() {
            System.out.println("添加用户");
        }
    
        @Override
        public void deleteUser() {
            System.out.println("删除用户");
        }
    }
    
  • 定义切面(实现Spring提供的拦截器)

    public class MyAspect implements org.aopalliance.intercept.MethodInterceptor {
        //定义三个通知
        public void before() {
            System.out.println("前置通知");
        }
    
        public void after() {
            System.out.println("后置通知");
        }
    
        public void around() {
            System.out.println("环绕通知");
        }
    
    
        @Override
        public Object invoke(MethodInvocation methodInvocation) throws Throwable {
            before();
            Object result = methodInvocation.proceed();
            after();
            return result;
        }
    }
    
    
  • 配置Spring中自带的工厂 applicationContext.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                               https://www.springframework.org/schema/beans/spring-beans.xsd
                               http://www.springframework.org/schema/context
                               https://www.springframework.org/schema/context/spring-context.xsd">
    
        <!--<bean id="userServiceFactory" class="com.it.framework.UserServiceFactory"></bean>-->
    
        <!--定义目标对象-->
        <bean id="userServiceImpl" class="com.it.framework.UserServiceImpl"></bean>
        <!--定义切面对象-->
        <bean id="myAspect" class="com.it.framework.MyAspect"></bean>
         <!--定义工厂对象-->
        <bean id="userServiceproxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <!--配置接口-->
            <property name="interfaces" value="com.it.framework.UserService"/>
            <!--配置目标对象-->
            <property name="targetName" value="userServiceImpl"/>
            <!--配置拦截器-->
            <property name="interceptorNames" value="myAspect"/>
            <!--配置动态代理方式,true是使用cglib的方式,默认使用jdk的动态代理-->
            <property name="optimize" value="true"></property>
        </bean>
    </beans>
    

6.2 Spring中的全自动AOP

  • pom依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.3.10.RELEASE</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.10.RELEASE</version>
        </dependency>
    
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.10.RELEASE</version>
        </dependency>
        <!--spring全自动aop依赖aspectj联盟的依赖-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.10</version>
        </dependency>
    </dependencies>
    
  • 定义接口===>同半自动AOP一致

  • 定义目标类===>同半自动AOP一致

  • 定义切面(实现Spring提供的拦截器)===>同半自动AOP一致

  • 配置applicationContext.xml

    <!--定义目标对象-->
    <bean id="userServiceImpl" class="com.it.framework.UserServiceImpl"></bean>
    
    <!--定义切面对象-->
    <bean id="myAspect" class="com.it.framework.MyAspect"></bean>
    
    <!--
            proxy-target-class=true表示使用cglib动态代理
        -->
    <aop:config proxy-target-class="true">
        <!--定义切点表达式-->
        <aop:pointcut id="myPointCut" expression="execution(* com.it.framework.UserServiceImpl.*(..))"/>
        <aop:advisor advice-ref="myAspect" pointcut-ref="myPointCut"></aop:advisor>
    </aop:config>
    
  • 入口类

        <!--定义目标对象-->
        <bean id="userServiceImpl" class="com.it.framework.UserServiceImpl"></bean>
    
        <!--定义切面对象-->
        <bean id="myAspect" class="com.it.framework.MyAspect"></bean>
    
        <!--
            proxy-target-class=true表示使用cglib动态代理
        -->
        <aop:config proxy-target-class="true">
                <!--定义切点表达式-->
                <aop:pointcut id="myPointCut" expression="execution(* com.it.framework.UserServiceImpl.*(..))"/>
                <aop:advisor advice-ref="myAspect" pointcut-ref="myPointCut"></aop:advisor>
        </aop:config>
    
    

7. 切点表达式

  • 用于描述需要增强的方法(切点)

  • 语法

    execution(修饰符  返回值  包..方法名(参数) throws异常)
    
  • 修饰符,一般省略

    public    		 公共方法
      *				 任意
    
  • 返回值类型,不能省略

    void         返回没有值
    String       返回值字符串
    *            任意
    
  • 包 可以省略

    ~~~java
    

    com.it.spring 固定包
    com.it.spring… spring包下面的所有子包(含自己)

  • 任意

       ~~~
  • 类,可以省略

    UserServiceImpl			指定类
    *ImplImpl结尾
    User*User开头
    *						任意
    
  • 方法名,不能省略

    addUser					固定方法
    add*					以add开头
    *DoDo结尾
    *						任意
    
  • (参数)

    ()						无参
    (int)					一个整型
    (int ,int)				两个
    (..)					参数任意
    
  • throws ,可省略,一般不写

  • eg

    UserServiceImpl类中任意参数的方法
    * com.it.framework.UserServiceImpl.*(..)
    

9. 基于Aspectj的AOP

  • AspectJ是一个基于Java语言的面向切面的AOP框架
  • Spring2.0以后新增了对AspectJ切点表达式支持
  • @AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面
  • 新版本Spring框架,建议使用AspectJ方式来开发AOP

9.1 AspectJ的增强类型

  • @Before 前置通知,相当于BeforeAdvice
@Before("execution(* com.uplooking.aop.UserDao.add*(..))")
public void beforeAdvice() {
    System.out.println("前置通知....");
}
  • @AfterReturning 后置通知,相当于AfterReturningAdvice
@AfterReturning(value = "execution(* com.uplooking.aop.UserDao.add*(..))", returning = "ret")
public void afterReturningAdvice(String ret) {
    System.out.println("后置通知.." + ret);
}
  • @Around 环绕通知,相当于MethodInterceptor
@Around("execution(* com.uplooking.aop.UserDao.add*(..))")
public void arounrAdvice(ProceedingJoinPoint pjp) throws Throwable {
    System.out.println("环绕通知前..");
    pjp.proceed();
    System.out.println("环绕通知后..");
}
  • @AfterThrowing抛出通知,相当于ThrowAdvice
@AfterThrowing("execution(* com.uplooking.aop.UserDao.add*(..))")
public void throwAdvice() {
    System.out.println("异常通知....");
}
  • @After 最终final通知,不管是否异常,该通知都会执行
@After(value = "execution(* com.uplooking.aop.UserDao.add*(..))")
public void afterAdvice() {
    System.out.println("最终通知....");
}

9.2. 基于Aspectj的Aop

  • pom依赖
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.10.RELEASE</version>
</dependency>
<!--Spring整合Aspectj的包-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>4.3.10.RELEASE</version>
</dependency>
  • 定义切面

    切面 = 切点  +  通知
    
/**
 * 切面 = 切点(切点表达式)  +  通知(方法)
 */
@Aspect
@Component
public class MyAspect {

    @Before("execution(* add*(..))")
    public void beforeAdvice() {
        System.out.println("前置通知....");
    }
}

  • 定义要增强的类
@Repository
public class UserDao {
    public void add() {
        System.out.println("添加用户...");
    }

    public void add1() {
        System.out.println("add1...");
    }

    public void delete() {
        System.out.println("删除用户...");
    }

    public void update() {
        System.out.println("修改用户...");
    }

    public void select() {
        System.out.println("查询用户...");
    }
}
  • 配置applicationContext.xml
<!--组件扫描器-->
<context:component-scan base-package="com.uplooking.aop"/>

<!--aop自动创建代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  • 测试程序
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class UserDaoTest {
    @Autowired
    private UserDao userDao;
	//edu.uplooking.com  passwd :80684
    @Test
    public void testAdd() {
        userDao.add();
        userDao.add1();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值