2:Spring AOP

AOP (Aspect Oriented Programming) 面向切面编程

OOP(Object Oriented Programming)面向对象编程,用对象的思想来完善程序

AOP是的OOP的一个补充,是在另外一个维度上抽象出的对象。

具体是指程序运行时动态的将非业务代码切入到业务代码中,从而实现程序的解耦合,将非业务抽象成一个对象,对对象编程就是面向对象编程。

在同样的地方有相同的方法抽象成一个切面----代码A切面对象。

AOP的优点:

  • 可以降低模块之间的耦合性
  • 提高代码的复用性
  • 集中管理代码的维护性
  • 集中管理代码的非义务代码,便于维护
  • 业务代码不受非业务代码的影响,逻辑更加清晰

    理解AOP

    1. 创建接口的计算器类

      package com.southwind.aop;

      public interface Cal {
      public int add(int num1,int num2);
      public int sub(int num1,int num2);
      public int mul(int num1,int num2);
      public int div(int num1,int num2);
      }

2.实现类:

package com.southwind.aop.impl;

import com.southwind.aop.Cal;

public class CalImpl implements Cal {
@Override
public int add(int num1, int num2) {
int result = num1+num2;
return result;
} @Override
public int sub(int num1, int num2) {
int result = num1-num2;
return result;
} @Override
public int mul(int num1, int num2) {
int result = num1*num2;
return result;
} @Override
public int div(int num1, int num2) {
int result = num1/num2;
return result;
}
}

3.日志打印:

  • 在每个方法开始的位置输出参数的信息
  • 在每个方法的结束的位置输出结果信息

    对于计算器而言,加减乘除是业务代码,日志是非业务代码。

    AOP如何实现?:

    使用动态代理

    代理首先具备CaLImpl的基础功能,然后在这个基础上扩展日志功能

    1. 删除CalImpl方法中的打印日志的代码,只保留业务代码
    2. 创建MyinvocationHandler类,实现IvocationHandler接口,生成动态代理类

      动态代理类要动态生成。

      ClassLoader用来将动态的类加载到虚拟机(JVM)中。

      Proxy.newProxyInstance(类加载器《object.getClass.getClassLoder》,委托对象的接口《object.getClass().getInterfaces()》,this);

      动态创建代理类---方到实体类里面。

底层原理

 1.接口:

 ```java
package com.southwind.aop; public interface Cal {
public int add(int num1,int num2);
public int sub(int num1,int num2);
public int mul(int num1,int num2);
public int div(int num1,int num2);
}

2.代理对象:

 package com.southwind.aop;

 import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays; public class MyinvocationHandler implements InvocationHandler {
//委托对象
private Object object=null;
//返回代理对象
public Object bind(Object object){
this.object=object;
return Proxy.newProxyInstance(object.getClass().getClassLoader(),
object.getClass().getInterfaces(),this);
} @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //实现业务代码和非业务代码调用 System.out.println(method.getName()+"方法的参数是:"+ Arrays.toString(args)); Object result=method.invoke(this.object,args); System.out.println(method.getName()+"方法的参数是:"+ result); return result; } } ``` 3.实现类; ```java
package com.southwind.aop.impl; import com.southwind.aop.Cal; public class CalImpl implements Cal {
@Override
public int add(int num1, int num2) {
int result = num1+num2;
return result;
} @Override
public int sub(int num1, int num2) {
int result = num1-num2;
return result;
} @Override
public int mul(int num1, int num2) {
int result = num1*num2;
return result;
} @Override
public int div(int num1, int num2) {
int result = num1/num2;
return result;
}
}

4.测试类:

```java
package com.southwind.test; import com.southwind.aop.Cal;
import com.southwind.aop.MyinvocationHandler;
import com.southwind.aop.impl.CalImpl; public class Test10 {
public static void main(String[] args) {
//实例化委托对象
Cal cal = new CalImpl();
// cal.add(10,3);
// cal.div(10,3);
// cal.mul(10,3);
// cal.sub(10,3);
// 获取代理对象
MyinvocationHandler myinvocationHandler= new MyinvocationHandler();
Cal proxy=(Cal)myinvocationHandler.bind(cal);
proxy.add(10,3); }
}

上述代码的动态机制实现了业务代码和非业务代码的解耦合,这是SpringAOP的底层实现机制,不要这么复杂,有更好的方式。

Spring AOP的开发步骤:

1.创建切面类:

package com.southwind.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component; import java.lang.reflect.Array;
import java.util.Arrays; @Component
@Aspect
public class LogAspect {
@Before("execution(public int com.southwind.aop.impl.CalImpl.*(..))")
public void before(JoinPoint joinPoint){
String name=joinPoint.getSignature().getName();
String args= Arrays.toString((joinPoint.getArgs()));
System.out.println(name+"方法的参数是"+args); }
@After("execution(public int com.southwind.aop.impl.CalImpl.*(..))")
public void after(JoinPoint joinPoint){
String name=joinPoint.getSignature().getName();
System.out.println(name+"方法执行完毕"); }
@AfterReturning(value = "execution(public int com.southwind.aop.impl.CalImpl.*(..))",returning = "result")
public void afterReturn(JoinPoint joinPoint,Object result){
String name=joinPoint.getSignature().getName();
System.out.println(name+"方法执行完毕"+"结果是:"+result); }
@AfterThrowing(value = "execution(public int com.southwind.aop.impl.CalImpl.*(..))",throwing = "ex")
public void afterTrowing(JoinPoint joinPoint,Exception ex){
String name= joinPoint.getSignature().getName();
System.out.println(name+"方法抛出异常"+ex);
} }

2.委托类加上@Component

package com.southwind.aop.impl;

import com.southwind.aop.Cal;
import org.springframework.stereotype.Component; @Component
public class CalImpl implements Cal {
@Override
public int add(int num1, int num2) {
int result = num1+num2;
return result;
} @Override
public int sub(int num1, int num2) {
int result = num1-num2;
return result;
} @Override
public int mul(int num1, int num2) {
int result = num1*num2;
return result;
} @Override
public int div(int num1, int num2) {
int result = num1/num2;
return result;
}
}

3.配置spring.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/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 扫包-->
<context:component-scan base-package="com.southwind.aop"></context:component-scan>
<!-- 自动代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

3测试类:

package com.southwind.aop.impl;

import com.southwind.aop.Cal;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("spring-aop.xml");
Cal cal = (Cal)applicationContext.getBean("a");
System.out.println(cal.add(10,3));
} }
  • @Component 将切面类加载到IoC容器中
  • @Aspect 表示类是一个切面类
  • @Before 表示方法执行的时机,execution表示的是切入点是CallImpl中执行add方法之前执行日志方法
  • @AfterReturning,表示方法的执行时机是再业务方法返回结果:returning是将返回的业务代码的返回的形参
  • @AfterThrowing:表示方法执行是抛出的异常,throwing表示抛出的异常的处理形参
  • aop:aspectj-autoproxy ,Spring IoC容器会结合动态代理对象自动的生成代理对象,AOP底层就是通过动态代理对象来实现的。

    AOP的概念:

    • 切面对象;根据切面抽象出来的对象,Callmpl所有的方法中需要加入日志的部分,抽象成一个切面对象
    • 通知:切面对象具体执行的代码,即具体的非业务代码,LoggerAspect对象打印日志的代码
    • 目标;被横切的对象,即CallImpl将通知加入其中。
    • 代理:切面对象、通知、目标混合之后的结果,即时我门使用JDK动态代理的机制创建对象
    • 连接点;需要被横切的位置,即要通知要插入业务代码的具体位置

最新文章

  1. ArcGIS Engine开发之图形查询
  2. java环境配置为1.7jdk为什么cmd java -version查看版本是1.8
  3. 【转】Java集合类
  4. iframe操作
  5. struts2 iterator排序
  6. java总结第二次//数组及面向对象
  7. Notepad++ 配置java编译环境
  8. 关于时间,日期,星期,月份的算法(Java中Calendar的用法)(一)
  9. Queue 消息的发送与接收(PTP 消息传递模型)
  10. C++随机数的使用方法
  11. struts异常:Caused by: Parent package is not defined: json-default - [unknown location]解决办法
  12. 移动端手势双击(MouseDown也可以在移动端响应,但是帧率太低)
  13. python-重载
  14. Java ----&gt; java io / java nio / java net 学习资源汇总
  15. 你想知道吗?come
  16. Python中的特殊属性与方法
  17. 图片转base64上传,视频同理。
  18. Flex4学习笔记2--代码保存在单独的文件中
  19. 【Hibernate】浅析hibernate中的延迟加载
  20. ssh 远程执行命令

热门文章

  1. kubernetes笔记-1-基础环境部署
  2. i春秋Upload
  3. JavaScript合集(流程控制语句)
  4. DHorse的链路追踪
  5. 【Shell案例】【tail/head/sed、echo $res &#183;&#183; cat和管道】2、打印文件的最后5行
  6. 单点登录系统使用Spring Security的权限功能
  7. 你不知道的Map家族中的那些冷门容器
  8. JavaScript:对象:如何去遍历输出一个对象的属性?语句for-in
  9. 8、ThreadPoolTaskExecutor线程并发
  10. CompletableFuture 使用总结