SpringAOP
SpringAOP
优点:
- 解藕
- 更好的代码复用
如何使用
- 创建maven项目,导入依赖
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.0.11.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.0.11.RELEASE</version> </dependency> </dependencies>
创建一个计算器接口,定义加减乘除方法
package org.csu.utils; 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); }
创建接口的实现类方法
package org.csu.utils.impl; import org.csu.utils.Cal; public class CalImpl implements Cal { public int add(int num1, int num2) { System.out.println("add方法的参数是["+ num1+","+num2+"]"); int result = num1 + num2; System.out.println("add方法的结果是["+ result+"]"); return result; } public int sub(int num1, int num2) { System.out.println("sub方法的参数是["+ num1+","+num2+"]"); int result = num1 - num2; System.out.println("sub方法的结果是["+ result+"]"); return result; } public int mul(int num1, int num2) { System.out.println("mul方法的参数是["+ num1+","+num2+"]"); int result = num1 * num2; System.out.println("mul方法的结果是["+ result+"]"); return result; } public int div(int num1, int num2) { System.out.println("div方法的参数是["+ num1+","+num2+"]"); int result = num1 / num2; System.out.println("div方法的结果是["+ result+"]"); return result; } }
上述代码中,日志信息与业务逻辑的耦合度很高,不利于系统的维护,使用AOP可以优化。可以通过动态***来实现AOP
给业务逻辑找一个***,打印日志信息的工作交给***来做,这样的话业务代码就只需要关注自身的业务即可。
package org.csu.utils; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; public class MyInvokationHandler implements InvocationHandler { //接受委托对象 private Object object = null; //返回***对象 public Object bind(Object object){ this.object = object; return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this); } 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; } }
以上通过动态***的方法实现AOP的过程,复杂且不好理解。Spring对AOP进行了封装,可以用面向对象的方法来实现AOP。
Spring不用创建InvocationHandler,只需要创建一个切面对象,将所有的非业务代码放在切面对象中完成即可。Spring会根据切面类以及目标类生成一个***对象
package org.csu.utils.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; import java.util.Arrays; @Component @Aspect public class LoggerAspect { @Before("execution(public int org.csu.utils.impl.CalImpl.*(..))") public void before(JoinPoint joinPoint){ //获取方法名 String name = joinPoint.getSignature().getName(); //获取参数 String args = Arrays.toString(joinPoint.getArgs()); System.out.println(name +"的aop参数是"+args); } }
两个注解:
- @Aspect : 表明该类是切面类
- @Component :把该类的对象注入到IOC容器中
spring.xml中配置aop
<?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-2.5.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"> <!-- 创建 SimpleDateFormat 实例并对这个实例进行实例化--> <!-- 自动扫描--> <context:component-scan base-package="org.csu"></context:component-scan> <!--使得asect注解生效,为目标类自动生成***对象--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
context:component-scan 将 org.csu包中所有类进行扫描,如果该类同时添加了 @Component,则将该类扫描到ioc容器中,让ioc管理他的对象
aop:aspectj-autoproxy 让spring结合切面类与目标类自动生成***对象
调用aop
package org.csu.utils.test; import org.csu.utils.Cal; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class test2 { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-aop.xml"); //获取***对象 Cal proxy =(Cal) applicationContext.getBean("calImpl"); proxy.add(6,7); } }