先说下spring aop的普通切面的配置.
首先是maven需要依赖下面这些jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.11</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.11</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.1_3</version>
</dependency>
其次是建立普通的接口和类,名字我是随便起的
package com.demo.aop.test;
public interface UserService {
void insert();
}
package com.demo.aop.test.impl;
import org.springframework.stereotype.Service;
import com.demo.aop.test.UserService;
@Service
public class UserServiceImpl implements UserService {
@Override
public void insert() {
System.out.println("userServiceImpl insert");
}
}
然后是建立切面类,目前只添加了前置方法
package com.demo.aop.test;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class UserAspect {
@Before("execution(void com.demo.aop.test.impl ..* .*(..))")
public void before() {
System.out.println("UserAspect insert");
}
}
最后是spring配置文件的配置
<?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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 自动扫描的包 -->
<context:component-scan base-package="com.demo.aop.test"></context:component-scan>
<!-- 配置启动代理 -->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>
最后就是测试方法了
package com.demo.aop.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserService userService = context.getBean(UserService.class);
userService.insert();
}
}
执行后如果看到下面这两行,说明配置成功了
前置通知被执行了,还有本来的方法也被执行了,如果你失败的话那可以看看我的另一篇文章,里面是具体的操作步骤,这里就不显示说了
http://blog.youkuaiyun.com/zxc_user/article/details/77856086
下面才是这篇文章要讲的东西,就是如果你想在类上面动态添加方法,如果修改原来的逻辑很复杂,那可以通过下面的方式进行为其代理类加上新的方法
首先,创建你新方法的接口和基本实现类
package com.demo.aop.test;
public interface OtherMethod {
void method();
}
package com.demo.aop.test.impl;
import com.demo.aop.test.OtherMethod;
public class OtherMethodImpl implements OtherMethod{
@Override
public void method() {
System.out.println("i am other method");
}
}
然后,新增一个类,如下
package com.demo.aop.test;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;
import com.demo.aop.test.impl.OtherMethodImpl;
@Component
@Aspect
public class ParentAspect {
// value 把当前的类注入到哪些代理类里面. + 号代表包括子类, defaultImpl 该接口的默认实现
@DeclareParents(value = "com.demo.aop.test.impl.UserServiceImpl+", defaultImpl = OtherMethodImpl.class)
public OtherMethod otherMethod;
}
然后是调用了
package com.demo.aop.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserService userService = context.getBean(UserService.class);
userService.insert();
//把 userService 强转为 OtherMethod,就可以获得他的方法了
OtherMethod otherMethod = (OtherMethod) userService;
otherMethod.method();
}
}
如果你看到下面的情况,那就表示代理上的代理已经成功了
至于为什么要用接口,道理很简单,就是你这个OtherMethod 的实现类以后可能会要修改,容易替换点