spring中的AOP编程思想详解

一.AOP编程思想介绍

1.servlet的AOP体现:

AOP意思就是面向切面编程,可以用一句话概况AOP编程思想,即横向重复,纵向抽取。我们知道,软件工程一个基本原则就是代码复用,为了实现这个目标,我们可以用类,用方法,同样,AOP也是代码复用的一种方式。我们现在用下面这样一种例子来具体解释什么叫做面向切面编程。熟悉 java web的朋友可能清楚,我们在编写servlet需要解决一系列的乱码问题,此时可以用filter一次性解决servlet乱码问题。此处的servlet中的乱码问题就是横向重复,而filter就是纵向抽取。可用下图表示此个例子。

2.SSH框架中的AOP思想体现

在SSH框架中,一个典型的例子就是service层中的事务管理,没一个service层都需要实现事务管理的代码,这就是所谓横向重复,spring能够为容器中的对象生成动态代理对象(spring中使用动态代理技术实现AOP),通过这个代理对象能够纵向管理事务操作。

具体如图解释。


二.spring实现AOP的原理解析

基本原理:通过生成代理对象,对原来的方法进行增强。根据生成对象的方式不同,分为两类。一类为动态代理,要求被代理的对象必须实现接口。一类为cglib代理,可以对任何类实现代理,原理为继承代理,若类被final修饰,则无法代理。

方式一解析:动态代理方式实现一个类中的方法

现在假设dao层有一个类UserDao,这个类有一个方法Save用来保存用户数据,一般在保存数据前,我们需要进行权限判断,而这个权限判断是为横向的重复操作,所以可以用AOP思想把它纵向抽取,然后通过动态代理技术把save方法增强,使其在进行保存之前进行权限判断。下面是动态代理的代码实现。

public class MyJDKProxy implements InvocationHandler//动态代理必须实现此接口
 {
private UserDao userDao;
public MyJDKProxy(UserDao userDao) {
this. userDao = userDao;
	}
//通过java中的代理类Proxy,生成UserDao的代理对象:
public UserDao createProxy(){
UserDao userDaoProxy = (UserDao)
Proxy. newProxyInstance(userDao.getClass().getClassLoader(),
userDao.getClass().getInterfaces(), this);
return userDaoProxy;
}
//此时模拟对方法进行增强,加入权限判断的代码
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
if("save".equals(method.getName())){
System. out.println("权限判断================");
}
return method.invoke(userDao, args);
}
}

方式二解析:Cglib动态代理技术生成一个代理对象。

Cglib是第三方的代理技术,被spring集成使用,原理是对目标对象进行继承代理,底层是字节码增强技术,生成当前类的子类对象。现在为上面的情况为save方法加入权限判断代码。Cglib动态代理对象的方式如下

public class MyCglibProxy implements MethodInterceptor{
private CustomerDao customerDao;
public MyCglibProxy(CustomerDao customerDao){
this. customerDao = customerDao;//获得需要增强方法的目标类
}
// 生成代理的方法:
public CustomerDao createProxy(){
// 创建 Cglib 的核心类:
Enhancer enhancer = new Enhancer();
// 设置父类:
enhancer.setSuperclass(CustomerDao. class);
// 设置回调:
enhancer.setCallback(this);
// 生成代理:
CustomerDao customerDaoProxy = (CustomerDao) enhancer.create();
return customerDaoProxy;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy
methodProxy) throws Throwable {
if("save".equals(method.getName())){
Object obj = methodProxy.invokeSuper(proxy, args);
System. out.println("权限判断================");
return obj ;
}
return methodProxy.invokeSuper(proxy, args);
}
}

三.spring中AOP开发详解

1.spring中AOP开发中的相关术语

Joinpoint(连接点): 目标对象中,所有可以增强的方

Pointcut(切入点): 目标对象所有已经增强的方法

Advice(通知/增强): 增强的代码

前置通知 :在目标方法执行之前执行.
后置通知 :在目标方法执行之后执行
环绕通知 :在目标方法执行前和执行后执行
异常抛出通知:在目标方法执行出现 异常的时候 执行
最终通知 :无论目标方法是否出现异常 最终通知都会 执行.

Target(目标对象): 代理的目标对象

Weaving(织入): 将通知应用到切入点的过程,spring 采用动态代理织入

Proxy(代理) : 将通知织入到目标对象后,形成代理对象。
Aspect(切面):切入点+通知

2.spring使用XML进行AOP的开发

spring内部已经实现了动态代理,在实际开发时,只需要准备后通知,然后在主配置文件中把通知配置到需要增强的方法中即可。
步骤一,导入AOP开发中所需要的jar包(四个)
1. spring-aspects-4.2.4.RELEASE.jar
2. spring-aop-4.2.4.RELEASE.jar
3.  com.springsource.org.aopalliance-1.0.0.jar

4. com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

步骤二,准备好目标对象

创建接口和类:
public interface UserService {
public void save();
public void update();
public void delete();
public void find();
}
public class UserServiceImpl implements UserService{
@Override
public void save() {
System. out.println("保存用户...");
}
@Override
public void update() {
System. out.println("修改用户...");
}
@Override
public void delete() {
System. out.println("删除用户...");
}
@Override
public void find() {
System. out.println("查询用户...");
}
}
步骤三,准备通知

public class Myadvice{
public void before()
{
System.out.println("前置增强")
}
public void afterReturning()
{
System.out.println("后置增强,出现异常不会调用")
}
public Object around(ProceedingJoinPoint pjp)throw Throwable{
System. out.println("环绕通知前的通知===========");
Object proceed=pjp.proceed();//调用目标方法
System. out.println("环绕通知后的通知===========");
return proceed;

}
public void afterException(){
System. out.println("出现异常调用===========");
}
public void after(){
System. out.println("后置增强,出现异常依然调用===========");
}
}

步骤四.配置讲通知织入目标对象中

目标类的配置

<! -- 目标类================ -->
<bean id="orderDao" class="com.cai.spring..UserServiceImpl">
</bean>
切面类的配置:
<! -- 配置切面类 -->
<bean id="myAspectXml" class="com.cai.spring.MyAdvice"></bean>

AOP的配置:

<aop:config>
<!-- 目标类的引入,可以用通配符-->
<aop:pointcut expression="execution(*
com.spring.UserServiceImpl.*(..))" id="pointcut1"/>
<! -- 配置切面 -->
<aop:aspect ref="myAdvice">

<aop:before method="before" point-ref"pointcut1"/>
<aop:aspect method="afterReturninf" point-ref"pointcut1"/>
		...其他几种通知配置如以上两种类似
</aop:aspect>
</aop:config>
至此,完成spring中AOP的XML全部配置

3.spring使用注解方式配置AOP

前四步与XML配置方式完全一致:导包--准备目标对象--准备通知--把目标对象和通知对象配置到主配置文件

区别在于:此种方式在在编写通知方法时用注解方式进行配置。以前置通知与后置通知为例。

@Aspect
//表明该类是一个通知类
public class MyAdvice {
//引入目标对象,这句话意思是方法切入点,execution为执行的意思,*代表任意返回值,然后是包名,
.*意思是包下面的所有子包。(..)代表各种方法.
@Pointcut("execution(*com.cai.service.ServiceImpl.*(...))")
public void pointcut1{}
// 前置增强
@Before("Myadvice.pointcut1()")
public void before(){
System. out.println("前置增强===========");
}
@AfterReturning("Myadvice.pointcut1()")
public void afterReturning(){
System. out.println("后置通知,出现异常不会调用===========");
}
.........其他几种类型的通知类似配置
四.总结

AOP思想是spring中至关重要的编程思想,也是spring如此强大的原因之一,使用AOP思想,可以完成如事务控制,日志记录,权限校验一一系列工作,方便开发进行。







  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值