一、实验目的:
(1)熟练掌握AOP术语(切面、切入点、通知等);
(2)熟练掌握基于XML和注解的AspectJ开发。
二、实验内容:
使用前置通知进行访问控制:通过方法参数决定是否可以访问该方法,当参数值为"agree"时允许访问,否则不允许访问。
三、实现方法与代码
方法1.基于XML的声明式AspectJ实现:
第一步:
1.建立dao接口(规范化模拟数据库访问)
package dao;
public interface TestDao {
public void visitdao(String str);
}
2.实现dao接口
package dao;
public class TestDaoImpl implements TestDao{
@Override
public void visitdao(String str) {
System.out.println("用户权限:"+str+";成功访问!!");
}
}
第二步:
1.定义切面
package aspectj.xml;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAspect {
/**
* 当参数值为“agree”时才可以访问
*/
public void before(JoinPoint pjp) throws Throwable{
System.out.println("====基于XML的声明式AspectJ的前置通知====");
//获取当前请求方法的参数值
Object[] args = pjp.getArgs();
if(args[0].toString().equals("agree")) {
System.out.println("请求成功!");
//执行目标类的方法(此处必须要抛出异常)
// Object obj = pjp.proceed();
}else {
System.out.println("请求失败,拒绝访问!");
// 由于前置通知是切入在方法执行前,所以为了防止他执行visitdao,此处抛出一个异常
// System.exit(-1);
if(true) {
throw new Exception("非法访问");
}
}
}
}
第三步:
xml配置文件
<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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--定义目标对象,被切的 -->
<bean id="testDao" class="dao.TestDaoImpl"/>
<!--定义切面,切别人的 -->
<bean id="myAspect" class="aspectj.xml.MyAspect"/>
<!--AOP配置-->
<aop:config>
<!-- 配置切面 -->
<aop:aspect ref="myAspect">
<!--配置切入点,通知增强哪些方法 -->
<aop:pointcut expression="execution(* dao.*.*(..))" id="pointcut"/>
<aop:before method="before" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
</beans>
第四步:
编写测试类(main):
package aspectj.xml;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import dao.TestDao;
public class AspectjXmlTest {
@SuppressWarnings("resource")
public static void main(String[] args) {
try{
//从xml加载容器
ApplicationContext appCon = new ClassPathXmlApplicationContext("/aspectj/xml/applicationContext.xml");
//从容器中获取到目标对象(被切类)
TestDao testDao = (TestDao)appCon.getBean("testDao");
//给目标对象方法参数传参
testDao.visitdao("agree");
testDao.visitdao("Topus");
}catch(Exception e){
System.out.println("出现异常:"+e); //打印异常信息
// e.printStackTrace(); //打印完整的异常信息
}
}
}
方法2.基于注解的声明式AspectJ
第一步:
同上,建立模拟的数据库操作dao类
第二步:
定义切面:(注解方式)
package aspectj.annotation;
import org.aspectj.lang.JoinPoint;
//import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyAspect {
//定义切入点
@Pointcut("execution(* dao.*.*(..))")
private void myPointCut() {
}
@Around("myPointCut()")
public Object before(JoinPoint pjp) throws Throwable {
System.out.println("====基于注解的声明式AspectJ的前置通知====");
//获取当前请求方法的参数值
Object[] args = pjp.getArgs();
if(args[0].toString().equals("agree")) {
System.out.println("请求成功!");
}else {
System.out.println("请求失败,拒绝访问!");
// 由于前置通知是切入在方法执行前,所以为了防止他执行visitdao,此处抛出一个异常
// System.exit(-1);
if(true) {
throw new Exception("非法访问");
}
}
return null;
}
}
第三步:
配置xml,此处只要指定扫描哪里的注解即可
<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:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--指定需要扫描的包,使注解生效 -->
<context:component-scan base-package="aspectj.annotation"/>
<!-- 启动基于注解的AspectJ支持 -->
<aop:aspectj-autoproxy/>
<!-- 控制反转 -->
<bean id="testDao" class="dao.TestDaoImpl"/>
</beans>
第四步:
创建测试类:
package aspectj.annotation;
//import java.util.Scanner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import dao.TestDao;
public class AspectjAnnotationTest {
public static void main(String[] args) {
try{
//从xml加载容器
@SuppressWarnings("resource")
ApplicationContext appCon = new ClassPathXmlApplicationContext("/aspectj/annotation/applicationContext.xml");
//从容器中获取到目标对象(被切类)
TestDao testDao = (TestDao)appCon.getBean("testDao");
//给目标对象方法参数传参
testDao.visitdao("agree");
testDao.visitdao("Topus");
}catch(Exception e){
System.out.println("出现异常:"+e); //打印异常信息
// e.printStackTrace(); //打印完整的异常信息
}
}
}