我们知道在面向对象OOP编程存在一些弊端,当需要为多个不具有继承关系的对象引入同一个公共行为时,例如日志,安全检测等,我们只有在每个对象里引入公共行为,这样程序中就产生了大量的重复代码,所以有了面向对象编程的补充,面向切面编程(AOP),AOP所关注的方向是横向的,不同于OOP的纵向。接下来我们就详细分析下spring中的AOP。首先我们从动态AOP的使用开始。
AOP的使用
在开始前,先引入Aspect。
<!-- aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectj.version}</version> </dependency>
创建用于拦截的bean
public class TestBean { private String message = "test bean"; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public void test(){ System.out.println(this.message); } }
创建Advisor
Spring中摒弃了最原始的繁杂配置方式而采用@AspectJ注解对POJO进行标注,使AOP的工作大大简化,例如,在AspectJTest类中,我们要做的就是在所有类的test方法执行前在控制台beforeTest。而在所有类的test方法执行后打印afterTest,同时又使用环绕的方式在所有类的方法执行前后在此分别打印before1和after1,以下是AspectJTest的代码:
@Aspect public class AspectJTest { @Pointcut("execution(* *.test(..))") public void test(){ } @Before("test()") public void beforeTest(){ System.out.println("beforeTest"); } @Around("test()") public Object aroundTest(ProceedingJoinPoint p){ System.out.println("around.....before"); Object o = null; try{ o = p.proceed(); }catch(Throwable e){ e.printStackTrace(); } System.out.println("around.....after"); return o; } @After("test()") public void afterTest() { System.out.println("afterTest"); } }
创建配置文件
要在Spring中开启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.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"> <aop:aspectj-autoproxy/> <bean id="test" class="com.yhl.myspring.demo.aop.TestBean"> <property name="message" value="这是一个苦逼的程序员"/> </bean> <bean id="aspect" class="com.yhl.myspring.demo.aop.AspectJTest"/> </beans>
测试
public class Test { public static void main(String[] args) { ApplicationContext bf = new ClassPathXmlApplicationContext("aspectTest.xml"); TestBean bean = (TestBean)bf.getBean("test"); bean.test(); } }
执行后输出如下:
Spring实现了对所有类的test方法进行增强,使辅助功能可以独立于核心业务之外,方便与程序的扩展和解耦。
那么,Spring是如何实现AOP的呢?首先我们知道,SPring是否支持注解的AOP是由一个配置文件控制的,也就是<aop:aspectj-autoproxy/>,当在配置文件中声明了这句配置的时候,Spring就会支持注解的AOP,那么我们的分析就从这句注解开始。
AOP自定义标签
之前讲过Spring中的自定义注解,如果声明了自定义的注解,