第一种使用Spring的API接口实现
写在前头:要实现AOP第一需要做的就是需要导入织入依赖包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
这种方式主要是需要自己写两个加强类
示例如下:
一个maven项目首先在用户客户端把接口和接口实现写好。
接口
package com.xkl.Service;
public interface UserService {
public void Add();
public void Delete();
public void Upgrade();
public void Query();
}
接口实现类:
package com.xkl.Service;
public class UserServiceImpl implements UserService{
@Override
public void Add() {
System.out.println("增加用户");
}
@Override
public void Delete() {
System.out.println("删除用户");
}
@Override
public void Upgrade() {
System.out.println("更新用户");
}
@Override
public void Query() {
System.out.println("查询用户");
}
}
接下来就是两个增强类的实现(这里以公共业务日志为例。都放在Log包内)
分别为:前置增强
package com.xkl.Log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class log implements MethodBeforeAdvice {
/*
* method:要执行的目标对象的方法。
* object:被调用的方法的参数
* o:目标对象
* */
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println(o.getClass().getName() + "的" + method.getName() + "方法被执行了");
}
}
后置增强
AfterLog
package com.xkl.Log;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class AfterLog implements AfterReturningAdvice{
/*
* returnvalue:返回值
* method:被调用的方法
* args:被调用的方法的对象的参数
* target:被调用的目标对象
* */
@Override
public void afterReturning(Object returnvalue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了" + target.getClass().getName() + "的" + method.getName() + "方法,返回值为:" + returnvalue);
}
}
将这三个类注册到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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="userService" class="com.xkl.Service.UserServiceImpl"/>
<bean id="log" class="com.xkl.Log.log"/>
<bean id="afterLog" class="com.xkl.Log.AfterLog"/>
<!--aop的配置-->
<aop:config>
<!--切入点 expression:表达式匹配要执行的方法-->
<aop:pointcut id="pointcut" expression="execution(*
com.xkl.Service.UserServiceImpl.*(..))"/>
<!--执行环绕:advice-ref 执行方法 。 point-ref 切入点-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
</beans>
最后进行测试:
import com.xkl.Service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class aopTest {
@Test
public void testQuery(){
ApplicationContext Context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = Context.getBean("userService", UserService.class);
userService.Query();
}
}
下图为一个maven项目包含的文件
第二种方法:自定义日志来实现AOP,这种方法主要是切入面的定义。(无需再自己写前置后置增强类)
第一步:接口和接口实现类就和第一种方法一样了。
第二步:接下来写一个我们自己的切入类:
package com.xkl.demo2.DiyAop;
/*
第二步:写我们自己的一个切入类。
* */
public class DiyPointcut {
public void before(){
System.out.println("------方法执行前------");
}
public void after(){
System.out.println("------方法执行后------");
}
}
第三步:将以上类配置到Spring容器中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<bean id="diy" class="com.xkl.demo2.DiyAop.DiyPointcut"/>
<bean id="userservice" class="com.xkl.demo2.UserService.UserserviceImpl"/>
<aop:config>
<!--第二种:使用aop的标签实现-->
<aop:aspect ref="diy">
<aop:pointcut id="diyPointcut" expression="execution(*
com.xkl.demo2.UserService.UserserviceImpl.*(..))"/><!--这个是切入点的选择-->
<aop:before method="before" pointcut-ref="diyPointcut"/>
<aop:after method="after" pointcut-ref="diyPointcut"/>
</aop:aspect>
</aop:config>
</beans>
与第一种方法的主要区别是:
自定义切面的注入,增强类就是引用自定义切面里面的方法。
第四步:进行测试
import com.xkl.demo2.UserService.Userservice;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AopSolutionTest {
@org.junit.Test
public void TestAop(){
ApplicationContext Context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
Userservice userservice = (Userservice) Context.getBean("userservice");
userservice.add();
}
}
第三种方法:用注释来实现AOP
**第一步的接口和接口实现类和以上方法都一样。
第二步:编写一个注释实现的增强类**
package com.xkl.demo3;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class AnnotationPointcut {
@Before("execution(* com.xkl.demo2.UserService.UserserviceImpl.*(..))")
public void before(){
System.out.println("------方法执行前------");
}
@After("execution(* com.xkl.demo2.UserService.UserserviceImpl.*(..))")
public void after(){
System.out.println("------方法执行后------");
}
@Around("execution(* com.xkl.demo2.UserService.UserserviceImpl.*(..))")
public void around(ProceedingJoinPoint jp) throws Throwable{
System.out.println("环绕前");
System.out.println("方法是:"+jp.getSignature());
//执行目标方法proceed
Object proceed = jp.proceed();
System.out.println("环绕后");
System.out.println(proceed);
}
}
第三步:将实现类和增强类注入到Spring容器中去。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<bean id="userservice" class="com.xkl.demo2.UserService.UserserviceImpl"/>
<bean id="annotationPointcut" class="com.xkl.demo3.AnnotationPointcut"/>
<aop:aspectj-autoproxy/>
</beans>
第四步:进行测试
import com.xkl.demo2.UserService.Userservice;
import com.xkl.demo3.AnnotationPointcut;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AopSolution2Test {
@Test
public void Mytest(){
ApplicationContext Context = new ClassPathXmlApplicationContext("ApplicationContext2.xml");
Userservice userservice = Context.getBean("userservice", Userservice.class);
userservice.add();
}
}
通过AOP命名空间的aop:aspectj-autoproxy/声明自动为spring容器中那些配置@aspect切面的bean创建代理,织入切面。当然,spring在内部依旧采用AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被 aop:aspectj-autoproxy/隐藏起来了。