您的位置:首页 > 编程语言 > Java开发

Spring(三)AOP的概述及其XML方式用法

2018-01-25 14:26 211 查看
1. AOP的概述



1.1 什么是AOP

 


Spring是解决实际开发中的一些问题:

* AOP解决OOP中遇到的一些问题.是OOP的延续和扩展.

1.2 为什么学习AOP

对程序进行增强:不修改源码的情况下.

* AOP可以进行权限校验,日志记录,性能监控,事务控制.

1.3 Spring的AOP的由来:

AOP最早由AOP联盟的组织提出的,制定了一套规范.Spring将AOP思想引入到框架中,必须遵守AOP联盟的规范.

1.4 底层实现:

代理机制:

* Spring的AOP的底层用到两种代理机制:

    * JDK的动态代理:针对实现了接口的类产生代理.

    * Cglib的动态代理:针对没有实现接口的类产生代理.应用的是底层的字节码增强的技术
生成当前类的子类对象.

 

2. Spring底层AOP的实现原理:(了解)

2.1 JDK动态代理增强一个类中方法:

public class MyJDKProxyimplements InvocationHandler
{

 

 private UserDaouserDao;

 

 public MyJDKProxy(UserDaouserDao)
{

  this.userDao =userDao;

 }

 

 //编写工具方法:生成代理:

 public UserDaocreateProxy(){

  UserDaouserDaoProxy =
(UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),

  userDao.getClass().getInterfaces(),this);

  return userDaoProxy;

 }

 @Override

 public Object invoke(Objectproxy,
Method method, Object[]args)throws Throwable {

  if("save".equals(method.getName())){

  System.out.println("权限校验================");

  }

  return method.invoke(userDao,args);

 }

}

2.2 Cglib动态代理增强一个类中的方法:

public class MyCglibProxyimplements MethodInterceptor{

 

 private CustomerDaocustomerDao;

 

 public MyCglibProxy(CustomerDaocustomerDao){

  this.customerDao =customerDao;

 }

 //生成代理的方法:

 public CustomerDao createProxy(){

  //创建Cglib的核心类:

  Enhancerenhancer =new Enhancer();

  //设置父类:

  enhancer.setSuperclass(CustomerDao.class);

  //设置回调:

  enhancer.setCallback(this);

  //生成代理:

  CustomerDaocustomerDaoProxy =
(CustomerDao)enhancer.create();

  return customerDaoProxy;

 }

 

 @Override

 public Object intercept(Objectproxy,
Method method, Object[]args, MethodProxy       methodProxy) throws Throwable
{

  if("delete".equals(method.getName())){

  Objectobj =methodProxy.invokeSuper(proxy,args);

  System.out.println("日志记录================");

  return obj;

  }

  return methodProxy.invokeSuper(proxy,args);

 }

}

3. Spring的基于AspectJ的AOP开发

3.1 AOP的开发中的相关术语:

Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点.

Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义.

Advice(通知/增强):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)

Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.

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

Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程.

spring采用动态代理织入,而AspectJ采用编译期织入和类装在期织入

Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类

Aspect(切面): 是切入点和通知(引介)的结合

4. Spring使用AspectJ进行AOP的开发:(XML的方式)

4.1 引入相应的jar包

* spring的传统AOP的开发的包

spring-aop-4.2.4.RELEASE.jar

com.springsource.org.aopalliance-1.0.0.jar

* aspectJ的开发包:

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

spring-aspects-4.2.4.RELEASE.jar

 


4.2 引入Spring的配置文件

引入AOP约束:

<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">
</beans>

4.3 编写目标类

创建接口和类:

public interface OrderDao {

 public void save();

 public void update();

 public void delete();

 public void find();

}

 

public class OrderDaoImplimplements OrderDao
{

 

 @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("查询订单...");

 }

 

}

4.4 目标类的配置

<!--
目标类================ -->

<bean id="orderDao" class="cn.itcast.spring.demo3.OrderDaoImpl">

</bean>

4.5 整合Junit单元测试

引入spring-test.jar

 

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration("classpath:applicationContext.xml")

public class SpringDemo3 {

 @Resource(name="orderDao")

 private OrderDaoorderDao;

 @Test

 public void demo1(){

  orderDao.save();

  orderDao.update();

  orderDao.delete();

  orderDao.find();

 }

}

4.6 通知类型

前置通知:在目标方法执行之前执行.

后置通知:在目标方法执行之后执行

环绕通知:在目标方法执行前和执行后执行

异常抛出通知:在目标方法执行出现异常的时候执行

最终通知:无论目标方法是否出现异常最终通知都会执行.

4.7 切入点表达式

execution(表达式)

表达式:

[方法访问修饰符]方法返回值 包名.类名.方法名(方法的参数)

public * cn.itcast.spring.dao.*.*(..)

* cn.itcast.spring.dao.*.*(..)

* cn.itcast.spring.dao.UserDao+.*(..)

* cn.itcast.spring.dao..*.*(..)

 

4.8 编写一个切面类

public class MyAspectXml {

//
前置增强

public void before(){

 System.out.println("前置增强===========");

}

}

4.9 配置完成增强

<!--
配置切面类 -->

<bean id="myAspectXml" class="cn.itcast.spring.demo3.MyAspectXml"></bean>

<!--
进行aop的配置 -->

<aop:config>

<!--
配置切入点表达式:哪些类的哪些方法需要进行增强-->

<aop:pointcut expression="execution(*
cn.itcast.spring.demo3.OrderDao.save(..))" id="pointcut1"/>

<!--
配置切面 -->

<aop:aspect ref="myAspectXml">

<aop:before method="before" pointcut-ref="pointcut1"/>

</aop:aspect>

</aop:config>

 

4.10 其他的增强的配置:

<!--
配置切面类 -->

<bean id="myAspectXml" class="cn.itcast.spring.demo3.MyAspectXml"></bean>

<!--
进行aop的配置 -->

<aop:config>

<!--
配置切入点表达式:哪些类的哪些方法需要进行增强-->

<aop:pointcut expression="execution(*
cn.itcast.spring.demo3.*Dao.save(..))" id="pointcut1"/>

<aop:pointcut expression="execution(*
cn.itcast.spring.demo3.*Dao.delete(..))" id="pointcut2"/>

<aop:pointcut expression="execution(*
cn.itcast.spring.demo3.*Dao.update(..))" id="pointcut3"/>

<aop:pointcut expression="execution(*
cn.itcast.spring.demo3.*Dao.find(..))" id="pointcut4"/>

<!--
配置切面 -->

<aop:aspect ref="myAspectXml">

<aop:before method="before" pointcut-ref="pointcut1"/>

<aop:after-returning method="afterReturing" pointcut-ref="pointcut2"/>

<aop:around method="around" pointcut-ref="pointcut3"/>

<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4"/>

<aop:after method="after" pointcut-ref="pointcut4"/>

</aop:aspect>

</aop:config>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: