Spring(三)AOP

1.手动实现AOP编程

AOP面向切面的编程:AOP可以实现业务代码与准备代码分离

代理工厂类

/**
 * 动态代理
 *(调用JDK中的API,在内存中动态的构建代理对象     目标对象必须实现接口时才能使用)
 * @author wsk
 *
 */
@Component
public class UserFactory_{
    private IUserDao target;
    private Aop aop;

    public UserFactory_(IUserDao target, Aop aop){
        this.target = target;
        this.aop = aop;
    }

    public Object getProxyInstance(){

        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(), 
                target.getClass().getInterfaces(), 
                new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {

                        aop.begin();

                        Object returnValue = method.invoke(target, args);

                        aop.end();

                        return returnValue;
                    }
                });
    }

}

配置

    <context:component-scan base-package="com.wsk.proxy_aop"></context:component-scan>
    <!-- 工厂方法创建代理后对象,非静态 -->
    <!-- 先创建工厂对象 调用带参数的构造器 -->
    <bean id="userFactory_" class="com.wsk.proxy_aop.UserFactory_" >
        <constructor-arg index="0" ref="userDao"></constructor-arg>
        <constructor-arg index="1" ref="aop"></constructor-arg>
    </bean>
    <!-- 然后用工厂类的方法创建代理对象 -->
    <bean id="proxy" factory-bean="userFactory_" factory-method="getProxyInstance"></bean>

2、AOP编程

关注点: 重复代码叫做关注点

切面:关注点形成的类,叫切面类

面向切面的编程,就是指对很多功能都有重复的代码抽取,在运行的时候往业务方法上动态植入切面代码。

切入点:执行目标对象方法,动态植入切面代码。

可以通过切入点表达式,指定拦截哪些类的哪些方法,给指定的类在运行的时候植入切面代码。

3.2 注解的方式实现AOP编程

(关键在于注解的切入点表达式@Pointcut(“execution(* cn.itcast.e_aop_anno..(..))”) 指定切入点表达式)
步骤:
1)引入AOP相关的jar文件

  • spring-aop-3.2.5.RELEASE.jar 【spring3.2.5
  • aopalliance.jar 【spring2.5源码/lib/aopalliance】
  • aspectjweaver.jar 【spring2.5源码/lib/aspectj】或【aspectj-1.8.2\lib】
  • aspectjrt.jar 【spring2.5源码/lib/aspectj】或【aspectj-1.8.2\lib】

2) bean.xml中引入aop名称空间

 xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemaLocation="
     http://www.springframework.org/schema/aop
     http://www.springframework.org/schema/aop/spring-aop.xsd">

3) 开启aop注解

     <!-- 开启注解扫描 -->
     <context:component-scan base-package="com.wsk.proxy_aop_note"></context:component-scan>
     <!-- 开启AOP注解方式 -->
     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

4) 使用注解

// 指定切入点表达式,拦截那些方法,即为那些类生成代理对象
@Aspect 指定一个类为切面类
@Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))") 指定切入点表达式

@Before("pointCut_()") 前置通知: 目标方法之前执行
@After("pointCut_()") 后置通知:目标方法之后执行(始终执行)
@AfterReturning("pointCut_()") 返回后通知: 执行方法结束前执行(异常不执行)
@AfterThrowing("pointCut_()") 异常通知: 出现异常时候执行
@Around("pointCut_()") 环绕通知: 环绕目标方法执行
<!-- 开启aop注解方式 -->
 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

示例代码

// 注解加入到容器中,并指定当前类为切面类
@Component
@Aspect
public class Aop {
    // 指定切入点表达式,拦截那些方法,即为那些类生成代理对象
    @Before("execution(* com.wsk.proxy_aop_note.*.*(..))")
    public void begin(){
        System.out.println("开启事务");
    }
    @After("execution(* com.wsk.proxy_aop_note.*.*(..))")
    public void end(){
        System.out.println("提交事务");
    }
}

或者写成

@Component
@Aspect
public class Aop {
    // 指定切入点表达式,拦截那些方法,即为那些类生成代理对象
    @Pointcut("execution(* com.wsk.proxy_aop_note.*.*(..))")
    public void pointCut(){
    }
    @Before("pointCut()")
    public void begin(){
        System.out.println("开启事务");
    }
    @After("pointCut()")
    public void end(){
        System.out.println("提交事务");
    }
}

测试类

/**
 * 注解方式配置Aop切面编程
 *      实现接口默认使用jdk代理,未实现接口的使用cglib代理
 * @author wsk
 *
 */
public class App {

    ApplicationContext ac = new ClassPathXmlApplicationContext("com/wsk/proxy_aop_note/bean.xml");

    @Test
    public void testAop(){
        // 目标对象实现接口使用JDK代理
        IUserDao proxy  = (IUserDao) ac.getBean("userDao");
        System.out.println(proxy.getClass());
        proxy.save();

        // 目标对象没有实现接口使用Cglib代理
        OrderDao orderDao = (OrderDao) ac.getBean("orderDao");
        System.out.println(orderDao.getClass());
        orderDao.save();

    }

}

目标对象实现接口,Spring采用JDK代理,目标对象没有实现接口,Spring使用Cglib代理

3.3 XML方式实现AOP编程

1)、引入jar文件【aop相关jar 4个】
2)、引入aop名称空间
3)、 AOP配置

     <!-- aop配置 -->
     <aop:config>

          <!-- 拦截指定方法 -->        
<!--      拦截指定包,及其子包下的所有方法   
          <aop:pointcut expression="execution(* com..*.*(..))" id="pt"/> -->
<!--      拦截save开头的所有方法   
          <aop:pointcut expression="execution(* save*(..))" id="pt"/> -->
<!-- 拦截指定类的所有方法     
          <aop:pointcut expression="execution(* com.wsk.proxy_aop_xml.UserDao.*(..))" id="pt"/> -->


          <aop:pointcut expression="execution(* com.wsk.proxy_aop_xml.*.*(..))" id="pt"/>

          <!-- 切面 -->
          <aop:aspect ref="aop">
              <!-- 前置通知 -->
              <aop:before method="begin" pointcut-ref="pt"/>
              <aop:after method="end" pointcut-ref="pt"/>
          </aop:aspect>
     </aop:config>

切入点表达式

定位切入的方法
public(可选) (返回值类型) com.wsk.proxy_aop_xml.(类名).*(方法名)(..)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值