Spring(三)AOP

来源:互联网 发布:汽车epc软件下载 编辑:程序博客网 时间:2024/05/20 09:47

1.手动实现AOP编程

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

代理工厂类

/** * 动态代理 *(调用JDK中的API,在内存中动态的构建代理对象     目标对象必须实现接口时才能使用) * @author wsk * */@Componentpublic 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@Aspectpublic 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@Aspectpublic 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.(类名).*(方法名)(..)

原创粉丝点击