spring_4Aop

基于注解的方式实现Aop
  1. 在业务层相应类加@component
  2. 写一个通知内容的切面类
    写一个通知内容的切面类把横切关注点的代码抽象到切面的类中,对业务层类进行切面通知,切面类首先是一个Ioc 中的bean,即加入@Componet 注解,切面还需加入@Aspect注解
    在切面类中写各种方法进行通知
    在切面类中方法前定义切点,方法上加@Before("execution(* classpath.(..))"),@After(),@AfterReturning(),@AfterThrowing()注解定义切点表示前置通知、后置通知、返回通知、异常通知。切点表达式是为了找到目标类的某些方法。表达式可以重用。环绕通知包括所有通知。
    比如,
    @Before(“execution(public Userdao.
    (..))”
    public void method(){...}
    表示在Userdao类任意方法执行之前要执行的method方法中的内容。
    在切面类的方法中声明一个类型为JoinPoint 的参数,然后能访问链接细节,如方法名和参数值
  3. 在配置文件中加入如下配置
<!-- 使AspectJ注解起作用:自动为匹配的类生成代理对象 -->  
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>  
  1. 在调用业务层的方法时,会有自定义的通知。
基于配置文件的方式实现Aop
  1. 业务层相应类
  2. 写切面类(不需要加@Aspect@Componet注解)
  3. 切面类相应的方法进行通知(不需要加@Before注解定义切点)
  4. 写xml配置文件
    <!-- 配置 bean -->
    <bean id="arithmeticCalculator" class="aopPeizhiImpl.ArithmeticCalculatorImpl"></bean>
    <!-- 配置切面的 bean. -->
    <bean id="loggingAspect" class="aopPeizhiImpl.LoggingAspect"></bean>
    <!-- 配置 AOP -->
    <aop:config>
        <!-- 配置切点表达式 -->
        <aop:pointcut id="pointcut" expression="execution(* aopPeizhiImpl.ArithmeticCalculator.*(int,int))" />
        
        <!-- 配置切面及通知 -->
        <aop:aspect ref="loggingAspect">
            <aop:before method="beforeMethod" pointcut-ref="pointcut"/>
            <aop:after method="afterMethod" pointcut-ref="pointcut"/>
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/>
            <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
        </aop:aspect>    
    </aop:config>  
  1. 在调用业务层的方法时,会有自定义的通知。
动态代理实现Aop
public class ArithmeticCalculatorLoggingProxy {
    //要代理的对象
    private ArithmeticCalculator target;
    
    public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target){
        this.target = target;
    }
    
    public ArithmeticCalculator getLoggingProxy(){
        
        //动态代理对象,在要代理对象的每个方法加了通知的内容
        ArithmeticCalculator proxy = null;
        
        //代理对象有哪一个类加载器负责加载
        ClassLoader loader  = target.getClass().getClassLoader();
        
        //代理对象的类型,即其中有哪些方法
        Class [] interfaces = new Class[]{ArithmeticCalculator.class};
        
        //当调用代理对象其中的方法时,该执行的代码
        InvocationHandler h = new InvocationHandler() {
            //proxy:正在返回的那个代理对象.
            //method:正在被调用的方法.
            //args:调用方法时,传入的参数.
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String methodName = method.getName();
                //打印日志
                System.out.println("invoke.."+methodName+" begin with "+Arrays.asList(args));
                Object result = null;
                try{
                    //这里写前置通知
                    
                    //调用目标方法
                    result = method.invoke(target, args);
                    
                    //这里写返回通知
                    
                }catch(Exception e){
                    e.printStackTrace();
                    //这里写异常通知
                    
                }
                //这里写后置通知
                
                //打印日志
                System.out.println("The method "+methodName+"end with"+result);
                return result;
            }
        };
        
        proxy  = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);
        return proxy;
    }
}  
public class Test {
    public static void main(String[] args) {
        ArithmeticCalculator target = new ArithmeticCalculatorImpl();
        ArithmeticCalculator proxy = new ArithmeticCalculatorLoggingProxy(target).getLoggingProxy();
        System.out.println(proxy.add(1, 2));
    }
}  
posted @ 2016-05-07 16:46  Taogen  阅读(241)  评论(0编辑  收藏  举报