Spring-静态代理和动态代理

目录

一、静态代理

1、代理类:

2、配置文件:

3、实现类:

4、测试类:

五、代码结构如下图:

 二、动态代理

1、创建service以及serviceImpl如下:

 2、创建domain如下:

3、配置文件applicationContext.xml :

4、processor如下:


一、静态代理

代理:

  • 在不修改目标类的目标方法代码前提下,为目标方法增加额外的功能
  • 代理类中也必须有同样的目标方法
  • 代理类实现跟目标类同样的接口
  • 如果目标类没有实现接口,代理类继承目标类
  • 基本上每个目标类都要编写一个代理类

核心是要手动创建一个代理类来实现service,然后配置文件中:注入的bean变成代理类,代理类中的target属性变成实现类。

1、代理类:

package com.mj.proxy;

import com.mj.service.UserService;

public class UserServiceProxy implements UserService {
    private UserService target;

    public void setTarget(UserService target) {
        this.target = target;
    }

    public boolean login(String username, String password) {
        System.out.println("这里写附加代码1");
        target.login(username,password);
        System.out.println("这里写附加代码2");
        return false;
    }
}
package com.mj.proxy;

import com.mj.service.SkillService;

public class SkillServiceProxy extends SkillService {

    private SkillService target;

    public void setTarget(SkillService target) {
        this.target = target;
    }

    @Override
    public boolean save(Object skill) {
        System.out.println("SkillServiceProxy ----- 1");
        boolean result = target.save(skill);
        System.out.println("SkillServiceProxy ----- 2");
        return result;
    }
}

 

2、配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userService" class="com.mj.proxy.UserServiceProxy">
        <property name="target" >
            <bean class="com.mj.service.impl.UserServiceImpl"/>
        </property>
    </bean>

    <bean id="skillService" class="com.mj.proxy.SkillServiceProxy">
        <property name="target" >
            <bean class="com.mj.service.SkillService"/>
        </property>
    </bean>

</beans>

3、实现类:

package com.mj.service.impl;

import com.mj.service.UserService;

public class UserServiceImpl implements UserService {

    public boolean login(String username, String password) {
        System.out.println("--login " + username + password);
        return false;
    }

}
package com.mj.service;

public class SkillService {
    public boolean save(Object skill) {
        System.out.println("SkillService --- save");
        return false;
    }
}

 

4、测试类:

 @Test
    public void test(){
        // 创建容器
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService service = ctx.getBean("userService", UserService.class);
        boolean result = service.login("小马哥","123456");
        // 关闭容器
        ctx.close();


        // 创建容器
        ClassPathXmlApplicationContext ctx1 = new ClassPathXmlApplicationContext("applicationContext.xml");
        SkillService service1 = ctx1.getBean("skillService", SkillService.class);
        service1.save(null);
        // 关闭容器
        ctx1.close();
    }

五、代码结构如下图:

 二、动态代理

动态代理有两种方案,一种是jdk的一种是cglib方案:

  • jdk自带的方案:必须要写加载器,并且只能对接口动态代理
  • cglib方案:内部会传一个类加载器,并且不只是对接口进行动态代理

1、创建service以及serviceImpl如下:

  • personService: void run();方法
  • userService: boolean login(String username, String password);方法
  • skillService是一个类:
public class SkillService {
    public boolean save(Object skill) {
        System.out.println("SkillService --- save");
        return false;
    }
}

 2、创建domain如下:

创建Person类以及相关方法如下:

public class Person {
    public void eat() {
        System.out.println("Person --- eat");
    }
}

3、配置文件applicationContext.xml :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


<!--    <bean class="com.mj.processor.LogProcessor"/>-->
    <bean class="com.mj.processor.LogProcessor2"/>
    <bean id="userService" class="com.mj.service.impl.UserServiceImpl"/>
    <bean id="personService" class="com.mj.service.impl.PersonServiceImpl"/>
    <bean id="skillService" class="com.mj.service.SkillService"/>

    <bean id="person" class="com.mj.domain.Person"/>

</beans>

4、processor如下:

  • jdk自带的动态代理相关配置:
package com.mj.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 会拦截每一个bean的生命周期,这个是jdk自带的动态代理方案,必须要写加载器,并且只能对接口动态代理
 */
public class LogProcessor implements BeanPostProcessor {

    public Object postProcessAfterInitialization(Object target, String beanName) throws BeansException {
      return   Proxy.newProxyInstance(getClass().getClassLoader(), // 类加载器,必须要有
                target.getClass().getInterfaces(),      // 代理类需要实现的接口(目标类的接口),必须要有接口不然会报错
                new LogInvocationHandler(target));      // 附加代码
    }


    private static class LogInvocationHandler implements InvocationHandler {
        private Object target;

        public LogInvocationHandler(Object target) {
            this.target = target;
        }

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

            // proxy: 代理对象
            // method:目标方法
            // args:目标方法的参赛
            System.out.println("proxy111-----------------1");
            // 调用目标对象的目标方法(核心业务代码)
            Object result = method.invoke(target,args);
            System.out.println("proxy222-----------------2");
            return result;
        }
    }
}

cglib动态代理相关配置:

package com.mj.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * 会拦截每一个bean的生命周期,CGlib方案,内部会传一个类加载器,并且不只是对接口进行动态代理
 */
public class LogProcessor2 implements BeanPostProcessor {
    public Object postProcessAfterInitialization(Object target, String beanName) throws BeansException {

        // 有些需要过滤
       if (!beanName.endsWith("Service")) return target;

        Enhancer enhancer = new Enhancer();
        enhancer.setClassLoader(getClass().getClassLoader());// cglib可以不要
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new LogMethodInterceptor(target));
        return enhancer.create();
    }

    private static class LogMethodInterceptor implements MethodInterceptor {
        private Object target;

        public LogMethodInterceptor(Object target) {
            this.target = target;
        }

        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println("proxy1-------------------");
            Object result = method.invoke(target,args);
            System.out.println("proxy2-------------------");
            return result;
        }
    }
}

测试工程结构如下图:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RiversTree

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值