关键字:idea引入jar包 ,面向切面编程
思路图:AOP 即 Aspect Oriented Program 面向切面编程
- 功能分两大类,辅助功能和核心业务功能
- 辅助功能和核心业务功能彼此独立进行开发
- 比如登陆功能,即便是没有性能统计和日志输出,也可以正常运行
- 如果有需要,就把"日志输出" 功能和 "登陆" 功能 编织在一起,这样登陆的时候,就可以看到日志输出了
- 辅助功能,又叫做切面,这种能够选择性的,低耦合的把切面和核心业务功能结合在一起的编程思想,就叫做切面编程
1. 准备业务类 ProductService
package com.jd.service;
public class ProductService {
public void doSomeService(){
System.out.println("doSomeService");
}
}
2.在引入切面之前,调用该业务类
//testSpring.java
package com.jd.test;
import com.jd.service.ProductService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class testSpring {
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
ProductService s = (ProductService) context.getBean("s");
s.doSomeService();
}
}
//spring-config.xml
<bean name="s" class="com.jd.service.ProductService">
</bean>
运行结果如图:3.引入jar包:aspectj-weaver.jar
当出现类找不到,其实就是没有导入相关的jar包,根据提示信息可以看到找不到XXX-aspectj-weaver-XXX相关的jar包,到官网下载XXX-aspectj-weaver-XXX相关的jar包,导入到lib文件目录。
在添加了jar包后,Intellij IDEA不会自动给我们build进去,下面我们手动build
4.准备日志切面 LoggerAspect
该日志切面的功能是 在调用核心功能之前和之后分别打印日志,切面就是原理图中讲的那些辅助功能。
Object object = joinPoint.proceed();
就是将来与某个核心功能编织之后,用于执行核心功能的代码
package com.jd.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
public class LoggerAspect {
public Object log(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("start log:" + joinPoint.getSignature().getName());
Object object = joinPoint.proceed();
System.out.println("end log:" + joinPoint.getSignature().getName());
return object;
}
}
getSignature()); //修饰符 + 包名 + 组件名(类名) + 方法的名字
getSignature().getName()); //方法名
getSignature().getDeclaringTypeName()); //包名 + 组件名(类名)
5. spring-config.xml
//声明业务类
<bean name="s" class="com.jd.service.ProductService">
</bean>
//声明日志切面
<bean id="loggerAspect" class="com.jd.aspect.LoggerAspect"/>
//指定核心业务功能
<aop:pointcut id="loggerCutpoint"
expression=
"execution( com.jd.service.ProductService.(..)) "/>
//指定左边的辅助功能
<aop:aspect id="logAspect" ref="loggerAspect">
<aop:around pointcut-ref="loggerCutpoint" method="log"/>
</aop:aspect>
然后通过aop:config把业务对象与辅助功能编织在一起。
execution(* com.jd.service.ProductService.*(..))
这表示对满足如下条件的方法调用,进行切面操作:
- *返回任意类型
- com.jd.service.ProductService.* 包名以 com.jd.service.ProductService 开头的类的任意方法
- (..) 参数是任意数量和类型
详细代码:
<?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/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">
<bean id="category" class="com.jd.java.Category">
<property name="name" value="Spring"></property>
</bean>
<bean name="p" class="com.jd.java.Product">
<property name="name" value="product" />
<property name="category" ref="category" />
</bean>
<bean name="s" class="com.jd.service.ProductService">
</bean>
<bean id="loggerAspect" class="com.jd.aspect.LoggerAspect">
</bean>
<aop:config>
<aop:pointcut id="loggerCutpoint"
expression=
"execution(*com.jd.service.ProductService.*(..)) "/>
<aop:aspect id="logAspect" ref="loggerAspect">
<aop:around pointcut-ref="loggerCutpoint" method="log"/>
</aop:aspect>
</aop:config>
</beans>
6.TestSpring
TestSpring 代码没有发生任何变化,通过配置的方式,把切面和核心业务类编制在了一起。
运行测试,可以发现在编织之后,业务方法运行之前和之后分别会打印日志