文章目录
一、代码
1.添加jar类库
2.按下图结构创建
3.配置上图代码
①CalculatorService类
package com.jd.calculator;
import org.springframework.stereotype.Service;
@Service
public class CalculatorService implements ICalculatorService {
@Override
public int mul(int a, int b) {
int result = a*b;
return result;
}
@Override
public int div(int a, int b) {
int result = a/b;
return result;
}
}
②ICalculatorService 接口
package com.jd.calculator;
public interface ICalculatorService {
int mul(int a, int b);
int div(int a, int b);
}
③CalculatorAspect类
package com.jd.calculator;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component/*将CalculatorAspect类创建对象并保存到Spring容器*/
public class CalculatorAspect {
//前置增强:在目标方法执行之前执行
@Before("execution(int mul(int, int))")
public void before(JoinPoint jp) {
Object target = jp.getTarget();
Object [] args = jp.getArgs();
String name = jp.getSignature().getName();
System.out.println(target.getClass().getName()+":The "+name+" method begins.");
System.out.println(target.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
}
//后置增强:在目标方法执行后执行,无论目标方法运行期间是否出现异常。注意:后置增强无法获取目标方法执行结果,可以在返回增强中获取
@After("execution(int mul(int, int))")
public void after(JoinPoint jp) {
Object target = jp.getTarget();
String name = jp.getSignature().getName();
System.out.println(target.getClass().getName()+":The "+name+" method ends.");
}
}
④配置application.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"
xmlns:context="http://www.springframework.org/schema/context"
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-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!-- 扫描并为含有注释的类创建对象 -->
<context:component-scan base-package="com.jd"></context:component-scan>
<!-- proxy-target-class="false"(默认值为false)创建的是JDK的动态代理,如果是true则创建的是CGLib的动态代理 -->
<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>
</beans>
⑤Test 测试类
package com.jd.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.jd.calculator.ICalculatorService;
public class Test {
public static void main(String[] args) {
//创建IOC容器并创建对象
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
//从IOC容器获取对象,由于已经为CalculatorService对象创建了代理对象,所以此时获取的对象为代理对象
//getBean(ICalculatorService.class)指通过ICalculatorService.class创建动态代理对象,所以ICalculatorService类需要是calculatorService动态代理对象的父类
ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);
System.out.println(calculatorService.getClass().getName());
int result = calculatorService.mul(1, 1);
System.out.println("-->"+result);
}
}
二、代码分析
1.执行过程
①先执行Test测试类中的main方法
②创建IOC容器
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
③跳转到application.xml文件中,通过扫描所有以com.jd开头的包为所有含有特定注解的类创建对象
<context:component-scan base-package="com.jd"></context:component-scan>
④Spring寻找有@Aspect注解的类——>寻找该类中方法——>获取方法注解 ——> 获取表达式(execution(int mul(int a, int b))——>检查Spring能扫描到的所有类,将与表达式匹配的方法对应的类——>为该类创建动态对象
<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>
⑤创建JDK的动态代理对象,这里是多态
ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);
⑥通过反射获得动态代理对象的名字
System.out.println(calculatorService.getClass().getName());
⑦先执行CalculatorAspect类中带有@Before注解的前置增强,再通过动态代理对象调用目标方法,最后执行CalculatorAspect类中带有@After注解的后置增强,将返回的值赋给result
int result = calculatorService.mul(1, 1);
⑧最后输出result的值
System.out.println("-->"+result);
2.如何使用JDK创建动态对象
把application.xml中aop:aspectj-autoproxy标签内的proxy-target-class属性设置为false
Test类中代码如下:
//如果创建的是JDK的动态代理,CalculatorService和动态类同级,没有继承关系会出错;
//而动态类是ICalculatorService的接口实现类,存在继承关系
ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);
执行结果如下
2.如何使用CGLib创建动态对象
把application.xml中aop:aspectj-autoproxy标签内的proxy-target-class属性设置为true
//如果创建的是CGLib的动态代理,CalculatorService是动态类的父类,存在继承关系
ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);
或
ICalculatorService calculatorService = applicationContext.getBean(CalculatorService.class);
执行结果如下
3.为什么没有引asm和CGLib的jar包,还可以用
因为Spring的jar包已经把他们融入了,见下图