如果注解类和目标类不在同一个包中,需要通过import引用注解类
住配置文件xx.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: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">
<!-- 加入新的约束文件spring-aop.xsd -->
<!-- 声明bean对象, 这个java对象是由spring创建的
id:自定义对象的名称, 这个名称是唯一值。 名称的定义语法和java变量的命名。
class:是必须的属性, 类的全限定名称。不能是接口
-->
<!-- 声明目标类对象 -->
<bean id="someServiceTarget" class="com.rdz.ba01.SomeServiceImpl" />
<!-- 声明切面类对象 -->
<bean id="myAspect" class="com.rdz.ba01.MyAspect" />
<!-- 声明组件扫描器:指定注解所在的包名, 让框架找到注解的位置
base-package:注解所在的包名,框架会扫描这个包和子包中的类,
按照类中的注解创建对象,给属性赋值。
-->
<context:component-scan base-package="com.rdz"/>
<!-- 声明自动代理生成器,创建目标对象的代理对象, 代理对象放入到spring容器 -->
<aop:aspectj-autoproxy />
<!-- 声明自动代理生成器,创建目标对象的代理对象, 代理对象放入到spring容器
proxy-target-class:true 表示使用cglib动态代理
-->
<aop:aspectj-autoproxy proxy-target-class="true" />
</beans>
业务类代码:
public class SomeServiceImpl implements SomeService {
@Override
public void doSome(String name, int age) {
System.out.println("====业务方法doSome====");
}
}
切面类代码:
import java.util.Date;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
/**
* @Aspect:来着aspectj框架,表示当前类是切面类。
* 切面类:是用来给目标方法增强功能的。
* 位置:在类的定义上面
*/
@Aspect
public class MyAspect {
//定义方法,实现功能的增强。 知道位置,给谁增强, 在什么时候增强
/**
* @Before: 前置通知
* 属性: value 表示切入点表达式, 表示切面执行的位置
* 位置: 在方法的定义上面
* 特点:
* 1.在目标方法之前执行的。
* 2.不会改变目标方法的执行结果
* 3.不会影响目标方法的执行
*/
// @Before(value="execution(* com.rdz.ba01.SomeServiceImpl.doSome(String, int))")
// public void myBefore(){
// //切面要执行的代码, 功能增强,例如日志处理
// System.out.println("前置通知:在目标方法之前执行的代码, 例如日志");
// }
// @Before(value="execution(* com.rdz.ba01.SomeServiceImpl.doSome(..))")
// public void myBefore(){
// //切面要执行的代码, 功能增强,例如日志处理
// System.out.println("前置通知:在目标方法之前执行的代码, 例如日志");
// }
// @Before(value="execution(* *..SomeServiceImpl.do*(..))")
// public void myBefore(){
// //切面要执行的代码, 功能增强,例如日志处理
// System.out.println("前置通知:在目标方法之前执行的代码, 例如日志");
// }
/**
* 给通知方法(myBefore)增加参数。
* 1.JoinPoint: 表示连接点, 表示业务方法,这个方法可以增加切面的功能。
* 通过JoinPoint能获取到方法的信息,方法的定义,方法的参数等等。
*/
@Before(value="execution(* *..SomeServiceImpl.do*(..))")
public void myBefore(JoinPoint jp){
//获取方法的信息
System.out.println("方法的定义:"+jp.getSignature());
//方法的参数信息
StringBuffer buffer = new StringBuffer();
Object args[] = jp.getArgs();
for(Object arg:args){
System.out.println(arg);
buffer.append(arg).append("|");
}
//切面要执行的代码, 功能增强,例如日志处理
System.out.println("前置通知:在目标方法之前执行的代码,
例如日志" +new Date()+"|"+ jp.getSignature().getName()+"|"+buffer.toString());
}
}
测试类代码:
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
String configLocation="com/rdz/ba01/applicationContext.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocation);
//代理对象
SomeService proxy = (SomeService) ctx.getBean("someServiceTarget");
//通过代理对象执行业务方法
proxy.doSome("zhangsan", 20);
}
@Test
public void test01(){
String configLocation="com/rdz/ba01/applicationContext.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocation);
//代理对象, 目标类有接口,默认使用jdk动态代理:com.sun.proxy.$Proxy6
SomeService proxy = (SomeService) ctx.getBean("someServiceTarget");
//System.out.println("proxy:"+proxy.getClass().getName());
//通过代理对象执行业务方法
proxy.doSome("zhangsan", 30);
}
}