面向切面编程(一)

来源:互联网 发布:linux ftp命令登录 编辑:程序博客网 时间:2024/06/05 07:27

spring AOP的核心设计思想是代理模式。

 spring AOP的主要功能是日志记录、性能统计、安全控制、事务处理、异常处理等等。spring AOP 可以将日志记录、性能统计、安全控制、事务处理、异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
      

一、AOP术语介绍:(其中连接点、切入点、切面比较重要)

       1.通知(Advice):通知定义了切面是什么以及何时使用。描述了切面要完成的工作和何时需要执行这个工作。
       2.连接点(Joinpoint):程序能够应用通知的一个“时机”,这些“时机”就是连接点,例如方法被调用时、异常被抛出时等等。
       3.切入点(Pointcut):通知定义了切面要发生的“故事”和时间,那么切入点就定义了“故事”发生的地点,例如某个类或方法的名称,spring中允许我们方便的用正则表达式来指定
       4.切面(Aspect):
通知和切入点共同组成了切面:时间、地点和要发生的“故事”
       
5.引入(Introduction):引入允许我们向现有的类添加新的方法和属性(Spring提供了一个方法注入的功能)
       
6.目标(Target):即被通知的对象,如果没有AOP,那么它的逻辑将要交叉别的事务逻辑,有了AOP之后它可以只关注自己要做的事(AOP让他做爱做的事)
       
7.代理(proxy):应用通知的对象,详细内容参见设计模式里面的代理模式
       
8.织入(Weaving):把切面应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机:
(1)编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器
(2)类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码
(3)运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理应该是使用了JDK的动态代理技术


二、前置通知

      所谓前置通知就是在用户对系统进行操作之前打印日志,比如登录之前会检测登录用户。前置通知实现的是MethodBeforeAdvice接口。

      示例代码:

      前置通知实现类CheckUser.java:     

package com.mfc.advice;import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;public class CheckUser implements MethodBeforeAdvice {public void before(Method method, Object[] objects, Object object) throws Throwable {String username = (String) objects[0]; System.out.println("正在对【"+username+"】用户进行身份检测...");}}

模拟用户登录接口UserLogin.java:

public interface UserLogin {public void login(String username);}

实现用户登录接口UserLoginImpl.java:

public class UserLoginImpl implements UserLogin {public void login(String username) {System.out.println(username+"正在登陆系统后台...");}}

测试类BeforeAdviceTest.java:

package com.mfc.test;import javax.jws.soap.SOAPBinding.Use;import org.springframework.aop.BeforeAdvice;import org.springframework.aop.framework.ProxyFactory;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.mfc.advice.CheckUser;import com.mfc.impl.UserLoginImpl;import com.mfc.interfaces.UserLogin;public class BeforeAdviceTest { public static void main(String[] args) { //方法一:直接在调用时生成代理/*UserLogin login = new UserLoginImpl();  //具体的登录用户BeforeAdvice advice = new CheckUser();  //前置通知ProxyFactory factory = new ProxyFactory();  //spring代理工厂factory.setTarget(login);  //设置代理目标factory.addAdvice(advice);  //为代理目标添加前置通知UserLogin proxy = (UserLogin) factory.getProxy();  //生成代理实例proxy.login("孟凡诚");  //调用登陆方法*///方法二:通过spring配置文件配置来声明代理 ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");UserLogin login=(UserLogin) applicationContext.getBean("userlogin");login.login("孟凡诚");}}

spring配置文件:

<bean id="checkUser" class="com.mfc.advice.CheckUser"></bean><bean id="target" class="com.mfc.impl.UserLoginImpl"></bean> <!-- 使用代理工厂配置一个代理 --><bean id="userlogin" class="org.springframework.aop.framework.ProxyFactoryBean"><!-- 指定代理接口,如果是多个接口,就使用list元素指定 --><property name="proxyInterfaces" value="com.mfc.interfaces.UserLogin"></property><!-- 指定通知 --><property name="interceptorNames" value="checkUser"></property><!-- 指定目标对象 --><property name="target" ref="target"></property></bean>

三、后置通知:

        所谓后置通知,就是在用户执行某一操作之后,进行日志输出。后置通知实现的是AfterReturningAdvice接口。

后置通知实现类:

public class WelcomeUser implements AfterReturningAdvice {public void afterReturning(Object object, Method method, Object[] objects, Object target) throws Throwable {String username = (String) objects[0];System.out.println("欢迎您:"+username+"登陆成功!");}}

配置文件:

<!-- 定义通知类 --><bean id="welcomeUser" class="com.mfc.advice.WelcomeUser"></bean><!-- 定义目标类 --><bean id="target" class="com.mfc.impl.UserLoginImpl"></bean><!-- 使用spring代理工厂配置一个代理 --><bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"><!-- 指定代理接口,如果是多个接口,就使用list元素指定 --><property name="proxyInterfaces" value="com.mfc.interfaces.UserLogin"></property><!-- 指定通知 --><property name="interceptorNames" value="welcomeUser"></property><!-- 指定目标对象 --><property name="target" ref="target"></property></bean>
测试类:

public class AfterAdviceTest {public static void main(String[] args) {ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");UserLogin login = (UserLogin) applicationContext.getBean("proxyFactoryBean");login.login("孟凡诚");}}

模拟用户登录的类同前置通知。


四、环绕通知:

        所谓的环绕通知,就是在用户对系统进行操作前后都会输出日志。实现MethodInterceptor接口。MethodInterceptor是AOP联盟接口。

环绕通知实现类:

package com.mfc.advice;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;public class CheckUserWelcome implements MethodInterceptor {public Object invoke(MethodInvocation invocation) throws Throwable {Object[] objs = invocation.getArguments();  //目标方法入参String username = (String) objs[0];//获取用户名//在目标方法执行前调用System.out.println("正在对【"+username+"】用户进行身份检测...");//通过反射调用执行方法Object object=invocation.proceed();//在目标方法执行后调用System.out.println("欢迎您:"+username+",登录成功!");return object;}}

spring配置:

<bean id="checkUserWelcome" class="com.mfc.advice.CheckUserWelcome"></bean><bean id="target" class="com.mfc.impl.UserLoginImpl"></bean><bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="proxyInterfaces" value="com.mfc.interfaces.UserLogin"></property><property name="interceptorNames" value="checkUserWelcome"></property><property name="target" ref="target"></property></bean>

测试类:

public class BeforeAdviceTest { public static void main(String[] args) { ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");UserLogin login=(UserLogin) applicationContext.getBean("proxyFactoryBean");login.login("孟凡诚");}}

五、异常通知:

       在目标方法抛出异常时调用。实现ThrowsAdvice接口。

用户登录的接口:

public interface UserLogin {public void login(String username);}
实现用户登录接口的类:

public class UserLoginImpl implements UserLogin {public void login(String username) {if(username.equals("孟凡诚")){System.out.println(username+"正在登陆系统后台...");}else{throw new RuntimeException("输入的 用户名不正确!");}}}

异常通知实现类:

public class CheckUser implements ThrowsAdvice {public void afterThrowing (Method method , Object[] objs , Object target , Exception exception){System.out.println("Method:"+method.getName()+"抛出异常:"+exception.getMessage());}}

spring配置文件:

<bean id="checkUser" class="com.mfc.advice.CheckUser"></bean><bean id="target" class="com.mfc.impl.UserLoginImpl"></bean><bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="proxyInterfaces" value="com.mfc.interfaces.UserLogin"></property><property name="interceptorNames" value="checkUser"></property><property name="target" ref="target"></property></bean>



原创粉丝点击