Settings

Spring 代理

一.静态代理原理实例:

项目结构:

IUserServ接口代码
[java] view plain copy

public interface IUserServ {  
    List<User> findAllUser();  
    int deleteUserById(User user);  
    int saveUser(User user);  
}  

UserServImpl实现类代码
[java] view plain copy

public class UserServImpl implements IUserServ {  
    public int deleteUserById(User user) {  
        System.out.println("******执行删除方法******");  
        return 0;  
    }  
    public List<User> findAllUser() {  
        System.out.println("*******执行查询方法*******");  
        return null;  
    }  
    public int saveUser(User user) {  
        System.out.println("*******执行添加方法********");  
        return 0;  
    }  
}  

UserServProxyImpl实现类代码
[java] view plain copy

//代理类:完成日志输出  
public class UserServProxyImpl implements IUserServ {  
    // 访问目标对象(UserServImpl)  
    // 代理对象(UserServProxyImpl)  
    // 创建目标对象  
    private IUserServ iuserServ ;//= new UserServImpl();  

    public UserServProxyImpl(IUserServ iuserServ){  
        this.iuserServ = iuserServ;  
    }  
    public int deleteUserById(User user) {  
        beforeLog();  
        //调用目标对象里方法  
        iuserServ.deleteUserById(user);  
        afterLog();  
        return 0;  
    }  

    public List<User> findAllUser() {  
        beforeLog();  
        //调用目标对象里方法  
        iuserServ.findAllUser();  
        afterLog();  
        return null;  
    }  

    public int saveUser(User user) {  
        beforeLog();  
        //调用目标对象里方法  
        iuserServ.saveUser(user);  
        afterLog();  
        return 0;  
    }  

    private void beforeLog() {  
        System.out.println("开始执行");  
    }  

    private void afterLog() {  
        System.out.println("执行完毕");  
    }  
}  

ActionTest测试类代码
[java] view plain copy

public class ActionTest {  
    public static void main(String[] args) {  
        //用户访问代理对象---信息->目标对象  
        IUserServ iuserServ = new UserServProxyImpl(new UserServImpl());  
        iuserServ.findAllUser();  
    }  
}  

运行结果:

开始执行
*执行查询方法*
执行完毕
二.动态代理实例

项目结构图:

IUserServ接口代码与UserServImpl实现类代码和上述代码相同

LogHandler类代码
[java] view plain copy

public class LogHandler implements InvocationHandler {  
    //目标对象  
    private Object targetObject;  
    /** 
     * 创建动态代理类 
     * @return object(代理类) 
     */  
    public Object createProxy(Object targetObject){  
        this.targetObject = targetObject;  
        return Proxy.newProxyInstance(  
                targetObject.getClass().getClassLoader(),   
                    targetObject.getClass().getInterfaces(), this);  
    }  
    @Override  
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        Object obj = null;  
        try {  
            beforeLog();  
            //obj: 目标对象--->代理对象的返回值--->返回给调用者的信息  
            //this.invoke("目标对象","代理对象给目标对象传递参数");  
            //调用目标对象中方法  
            obj = method.invoke(targetObject, args);  
            afterLog();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return obj;  
    }  

    //日志管理方法  
    private void beforeLog(){  
        System.out.println("开始执行");  
    }  

    private void afterLog(){  
        System.out.println("执行完毕");  
    }  

}  

ActionTest测试类代码:
[java] view plain copy

public class ActionTest {  
    public static void main(String[] args) {  
        //创建代理对象iuserServ  
        LogHandler handler = new LogHandler();  
        IUserServ iuserServ = (IUserServ)handler.createProxy(new UserServImpl());  
        iuserServ.deleteUserById(new User());  
    }  
}  

运行结果:
开始执行
*执行删除方法*
执行完毕
三.Spring AOP使用(2.x版本之前)

项目结构图:

IUserServ接口代码与UserServImpl实现类代码和上述代码相同

配置步骤:

1、配置目标对象(applicationContext.xml)
[html] view plain copy

<bean id="userServTarget" class="com.tarena.biz.impl.UserServImpl"/>   

2、配置通知
(a)前置通知(BeforeLogAdvice)
[java] view plain copy

public class BeforeLogAdvice implements MethodBeforeAdvice {  
     /** 
        * Method method:调用目标对象的方法 
        * Object[] args:发送给目标对象的参数列表 
        * Object target:目标对象 
        */  
    public void before(Method method, Object[] args, Object target)  
            throws Throwable {  
        beforeLog();  
    }  
    private void beforeLog(){  
        System.out.println("开始执行");  
    }  
}  

(b)后置通知(AfterLogAdvice)
[java] view plain copy

public class AfterLogAdvice implements AfterReturningAdvice {  
      /** 
        * Object returnValue:目标对象返回值 
        *  Method method:目标对象方法名 
        *  Object[] args:目标对象参数列表 
        *  Object target:目标对象 
        */  
    public void afterReturning(Object returnValue, Method method,  
            Object[] args, Object target) throws Throwable {  
        afterLog();  
    }  
    private void afterLog(){  
        System.out.println("执行完毕");  
    }  
}  

(c)在spring容器中,让容器管理通知(applicationContext.xml)
[html] view plain copy

<!-- 定义通知 -->  
        <!-- 前置通知 -->  
        <bean id="beforeLogAdvice" class="com.tarena.advice.BeforeLogAdvice"/>  
        <!-- 后置通知 -->  
        <bean id="afterLogAdvice" class="com.tarena.advice.AfterLogAdvice"/>  

3、配置代理对象(applicationContext.xml)
[html] view plain copy

<!-- 代理类作用: 生成代理类,织入通知 -->    
  <bean id="userServProxy"   
   class="org.springframework.aop.framework.ProxyFactoryBean">  
   <property name="interfaces">  
   <!-- 可以添加多个接口 -->  
    <list>  
     <value>com.tarena.biz.IUserServ</value>  
    </list>  
   </property>  
   <!-- 引入通知 -->  
   <property name="interceptorNames">  
    <list>  
     <value>beforeLogAdvice</value>  
     <value>afterLogAdvice</value>  
    </list>  
   </property>  
   <!-- 目标对象 -->  
   <property name="target" ref="userServTarget"/>  
  </bean>  

4.访问()
Spring容器:通过代理对象调用–>织入通知—>目标对象
程序员:访问代理对象

测试类(ActionTest):
[java] view plain copy

public class ActionTest {  
    public static void main(String[] args) {  
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");  
        IUserServ iuserServ = (IUserServ)ac.getBean("userServProxy");  
        iuserServ.deleteUserById(new User());  
        iuserServ.findAllUser();  
    }  
}  

运行结果:

开始执行
*执行删除方法*
执行完毕
开始执行
*执行查询方法*
执行完毕
四.Spring AOP使用(2.x版本之后)这种方式需要额外添加两个jar包,

存放位置在spring-framework-2.5.6.SEC01\lib\aspectj文件夹下。

项目结构图

IUserServ接口代码与UserServImpl实现类代码和上述代码相同

LogAdvice中
[java] view plain copy

public class LogAdvice {  
    public void beforeLog(){  
        System.out.println("开始执行");  
    }  
    public void afterLog(){  
        System.out.println("执行完毕");  
    }  
}  

applicationContext.xml中
[html] view plain copy

<!-- spring2.x后 -->  
    <!-- 目标对象 -->  
    <bean id="userServImpl" class="com.tarena.biz.impl.UserServImpl"/>  
    <!-- 通知 -->  
    <bean id="logAdvice" class="com.tarena.advice.LogAdvice"/>  

    <aop:config>  
        <aop:aspect id="logAspect" ref="logAdvice">  
            <!-- 切入点 -->  
            <aop:pointcut id="beforePointCut"   
        expression="execution(* saveUser*(..))"/>  
        <aop:pointcut id="afterPointCut"   
        expression="execution(* saveUser*(..))"/>  

            <!-- 织入(通知作用于切入点) -->  
            <aop:before method="beforeLog" pointcut-ref="beforePointCut"/>  
            <aop:after method="afterLog" pointcut-ref="afterPointCut"/>  
        </aop:aspect>  
    </aop:config>  

测试类:
[java] view plain copy

public class ActionTest {  
    public static void main(String[] args) {  
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");  
        IUserServ iuserServ = (IUserServ)ac.getBean("userServImpl");  
        iuserServ.deleteUserById(new User());  
        iuserServ.findAllUser();  
        iuserServ.saveUser(new User());  
    }  
}  

运行结果
*执行删除方法*
*执行查询方法*
开始执行
*执行添加方法**
执行完毕

注:如果要在业务层所有的方法前后添加日志文件,则需要更改为以下配置
[html] view plain copy

<aop:pointcut id="beforePointCut"   
        expression="execution(* com.tarena.biz.*.*(..))"/>  
        <aop:pointcut id="afterPointCut"   
        expression="execution(* com.tarena.biz.*.*(..))"/>  

运行结果:

开始执行
*执行删除方法*
执行完毕
开始执行
*执行查询方法*
执行完毕
开始执行
*执行添加方法**
执行完毕

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值