分离了重复代码:关注点
关注点代码:产生类即切面类
开启代理模式
实现接口的类,Spring默认使用JDK代理;未实现接口的类,Spring默认使用Cglib代理
@Before("execution(public void com.asd.spring.UserDao.save())")
@After("execution(public void com.asd.spring.UserDao.save())")
① 接口实现类(UserDao.java)、未实现类(OrderDao.java)和切面类(MyAop.java)都不需要用注解;② 不用注解的方式则xml中不需要开启注解扫描和开启代理模式,需要在 xml文件中生成对应的 bean对象:xml 文件中有生成UserDao、OrderDao、切面类MyAop对象;可以在< aop:before>标签中用 pointcut属性单独书写每一个切入点表达式;也可以在< aop:pointcut>用 expression属性统一书写切入点表达式, express属性中可以用 “||”和“or”来写多个表达式,再在< aop:before>标签中用 pointcut-ref属性引用它;
// eg:
eg: 1. 使用 AspectJ实现 AOP(注解方式)
1.1 IUserDao.java
public interface IUserDao{
public void save() throws Exception;
public void update() throws Exception;
}
1.2 UserDao.java
(此目标对象实现接口)
@Component("userDao")
public class UserDao implements IUserDao{
public void save() throws Exception{
System.out.println("----数据已保存----");
// int i=1/0;
}
public void update() throws Exception{
System.out.println("----数据已修改----");
}
}
1.2(1) OrderDao.java
(新增一个OrderDao,不实现接口)
@Component("orderDao")
public class OrderDao{
public void update() throws Exception{
System.out.println("----修改订单----");
}
}
1.3 MyAop.java
(① 目标对象提取后形成的单独类:@Aspect注解表示这是一个切面类;@Before(“execution(public void com.asd.spring.UserDao.save())”) 是切入点表达式;② 若在UserDao.java中出现异常,此时@AfterReturning不执行;③ 为避免重复书写切入点表达式,可以用@PointCut注解写一个切入点方法,无需实现;后面注解中只需要引用方法即可,不需要再多次书写切入点表达式;)
@Component
@Aspect
public class MyAop{
//@PointCut("execution(public void com.asd.spring.UserDao.save())")
@PointCut("execution(* *.*())")
public void pointCut(){
}
//@Before("execution(public void com.asd.spring.UserDao.save())")
@Before("pointCut()")
public void beginTrans(){
System.out.println("开始事务");
}
//@After("execution(public void com.asd.spring.UserDao.save())")
@After("pointCut()")
public void commitTrans(){
System.out.println("提交事务");
}
//@AfterReturning("execution(public void com.asd.spring.UserDao.save())")
@AfterReturning("pointCut()")
public void afterReturning(){
System.out.println("afterReturning");
}
//@AfterThrowing("execution(public void com.asd.spring.UserDao.save())")
@AfterThrowing("pointCut()")
public void afterThrow(){
System.out.println("afterThrow");
}
//@Around("execution(public void com.asd.spring.UserDao.save())")
@Around("pointCut()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("begin");
joinPoint.proceed();
System.out.println("end");
}
}
1.4 bean.xml
(xml文件中有: xmlns:context、 xmlns:aop、xmlns:tx即context、aop、tx命名空间, )
Test.java
public class Test{
public static void main(String[] args) {
ApplicationContext applicationContext=new ApplicationContext("bean.xml");
IUserDao userDao=(IUserDao)applicationContext.getBean("userDao");
System.out.println(userDao.getClass());//userDao对象(即实现接口的目标对象)类型
try{
userDao.save();
userDao.update();
}catch(Exception e){
e.printStackTrace();
}
System.out.println("-------------");
OrderDao orderDao=(OrderDao)applicationContext.getBean("orderDao");
System.out.println(orderDao.getClass());//orderDao对象(即没有实现接口的目标对象)类型
try{
orderDao.update();
}catch(Exception e){
e.printStackTrace();
}
}
}
① MyAop.java切面类中只有 @Before、@After 注解时,运行结果:
② MyAop.java切面类中增加 @AfterReturning 注解后且无异常,运行结果: / 出现异常运行结果:
③ MyAop.java切面类中增加 @AfterThrowing 注解后且出现异常,运行结果:
④ MyAop.java切面类中增加 @Around 注解后运行结果:
⑤ 增加 OrderDao.java 类后,切面类 MyAop.java中切入点表达式方法只限定OrderDao(即未改为全部即 * )注解后运行结果:(没有执行切入点代码)
⑤ 增加 OrderDao.java 类、且在UserDao.java类中添加 update() 方法,切面类 MyAop.java中切入点表达式方法为全部类和方法(即 * )后运行结果:(有执行切入点代码)
⑥ 输出两个对象userDao对象(实现接口)、orderDao对象(没实现接口)运行结果:
userDao对象类型:class com.sun.proxy.$Proxy12
orderDao对象类型:class com.asd.spring.OrderDao $ $EnhancerBySpringCGLIB $ $ 87c00f1f
【 可看出实现接口的类Spring默认使用JDK代理,未实现接口的类Spring默认使用Cglib代理 】
(① 接口实现类(UserDao.java)、未实现类(OrderDao.java)和切面类(MyAop.java)都不需要用注解;② 不用注解的方式则xml中不需要开启注解扫描和开启代理模式,需要在 xml文件中生成对应的 bean对象:xml 文件中有生成UserDao、OrderDao、切面类MyAop对象;可以在< aop:before>标签中用 pointcut属性单独书写每一个切入点表达式;也可以在< aop:pointcut>用 expression属性统一书写切入点表达式, express属性中可以用 “||”和“or”来写多个表达式,再在< aop:before>标签中用 pointcut-ref属性引用它;)
2.1 IUserDao.java
public interface IUserDao{
public void save() throws Exception;
public void update() throws Exception;
}
2.2 UserDao.java
public class UserDao implements IUserDao{
public void save() throws Exception{
System.out.println("----数据已保存----");
// int i=1/0;
}
}
2.2(1) OrderDao.java
public class OrderDao{
public void update() throws Exception{
System.out.println("----修改订单----");
}
}
2.3 MyAop.java
public class MyAop{
public void beginTrans(){
System.out.println("开始事务");
}
public void commitTrans(){
System.out.println("提交事务");
}
public void afterReturning(){
System.out.println("afterReturning");
}
public void afterThrow(){
System.out.println("afterThrow");
}
public void around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("begin");
joinPoint.proceed();
System.out.println("end");
}
}
2.4 bean.xml
(xml 文件中有生成UserDao、OrderDao、切面类MyAop对象,可以在< aop:before>标签中用 pointcut属性单独书写每一个切入点表达式;也可以在< aop:pointcut>用 expression属性统一书写切入点表达式, express属性中可以用 “||”和“or”来写多个表达式,再在< aop:before>标签中用 pointcut-ref属性引用它;)
// //统一写切入点表达式,再在下面pointcut-ref引用其id
// //用“||”和“or”都可以
// //分开写
Test.java
在这里插入代码片