Spring使用JavaConfig实现配置+代理模式

本文介绍了如何在Spring项目中使用JavaConfig替代XML配置,详细讲解了环境搭建过程,并探讨了代理模式,包括静态代理和动态代理的概念、优缺点及示例代码,展示了其在SpringAOP中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JavaConfig

  1. 让Spring项目全权交给Java来做,拜托了xml配置文件
  2. JavaConfig是Spring的子项目,Spring4之后,成为了一个核心功能

环境搭建

  1. 创建新模块,选择Spring
  2. 创建文件夹config,配置UserBean
package com.bkms.config;

import com.bkms.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration//该注释修饰的也会交由Spring容器托管,因为该容器本身也是@Component
//@Configuration也是配置类,和beans.xml是一样的
@Import(MyConfig2.class)//导入MyConfig2的bean
public class MyConfig {
	//@Bean注解就相当于在xml文件中的bean标签
	//方法的名字就相当于bean标签中的id属性
	//方法中的返回值就相当于bean标签中的class属性
    @Bean
    public User getUserInstance(){
        return new User();//就是返回要注入到bean的对象
    }
}
  1. 测试代码
import com.bkms.config.MyConfig;
import com.bkms.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        User userInstance = (User) context.getBean("getUserInstance");
        System.out.println(userInstance.getName());//null
    }
}
  1. 这种JavaConfig配置方式在SpringBoot中随处可见

代理模式

  1. SpringAOP的底层
  2. SpringAOP和SpringMVC是很重要的知识点
  3. 分为静态代理和动态代理

静态代理模式

角色分析(以租房举例)

  1. 抽象角色(租房这个行为,用接口表示)
  2. 真实角色(就是房东)
  3. 代理角色(就是中介)
  4. 客户(就是要租房的人)

使用代理模式的好处

  1. 使真实角色操作更加纯粹,不用关注多余的业务
  2. 实现了业务的分工
  3. 公共业务需要扩展的时候,方便集中管理

使用代理模式的缺点

  1. 一个真是角色对应一个代理角色,真实角色多的话,代理角色会翻倍
public interface Rent {
    public void rent();
}
public class Host implements Rent {
    public void rent() {
        System.out.println("house host sale");
    }
}
public class Proxy implements Rent{
    private Host host1;

    public Proxy() { }

    public Proxy(Host host1) {
        this.host1 = host1;
    }

    public void rent() { 
		host.rent();
		//add more code here...
	}
}
public class Client {
    public static void main(String[] args) {
        Host host = new Host();
        Proxy proxy = new Proxy(host);
        proxy.rent();
    }
}

静态代理示例代码

在调用某方法前输出日志,体现了面向AOP编程的思想

  1. 接口
package com.bkms.demo02;

public interface UserService {
    public void add();
    public void delete();
    public void modify();
    public void query();
}
  1. 接口实现类
package com.bkms.demo02;

public class UserServiceImpl implements UserService {
    public void add() {
        System.out.println("add");
    }

    public void delete() {
        System.out.println("delete");
    }

    public void modify() {
        System.out.println("modify");
    }

    public void query() {
        System.out.println("query");
    }
}
  1. 代理
package com.bkms.demo02;

import java.lang.reflect.Method;

public class UserServiceProxy implements UserService {

    private UserServiceImpl userService;

    public void setUserService(UserServiceImpl userService) {
        this.userService = userService;
    }

    public UserServiceProxy() {
    }

    /**
     * 获取完整方法名称
     * @param msg 方法名称
     * @return
     */
    public String getMethodName(String msg){
        Class<UserServiceProxy> uClass = UserServiceProxy.class;
        try {
            Method m = uClass.getMethod(msg);
            return m.toString();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 打印日志方法
     * @param msg 方法名称
     */
    public void log(String msg){
        System.out.println("use "+msg+" method");
    }

    /**
     * 增删改查方法
     */
    public void add() {
        log(getMethodName("add"));
        userService.add();
    }
    public void delete() {
        log(getMethodName("delete"));
        userService.delete();
    }
    public void modify() {
        log(getMethodName("modify"));
        userService.modify();
    }
    public void query() {
        log(getMethodName("query"));
        userService.query();
    }
}
  1. 用户
package com.bkms.demo02;

public class Client {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        UserServiceProxy userServiceProxy = new UserServiceProxy();

        userServiceProxy.setUserService(userService);
        userServiceProxy.add();
    }
}

动态代理模式

  1. 动态代理的代理类是动态生成的,不是直接写好的
  2. 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
  • 基于接口:JDK动态代理
  • 基于类:cglib
  • java字节码实现:javasist
  1. 需要了解2个类
  • Proxy:代理
  • InvocationHandler:调用处理程序
  1. 动态代理的本质,是通过反射机制实现
  2. 集中管理,实现业务分工
  3. 一个动态代理代理的是一个接口,一般是对应的一类业务

动态代理示例代码

  1. 例1
//Host.java
package com.bkms.demo03;

public class Host implements Rent {
    public void rent() {
        System.out.println("sale house");
    }

    public void contract() {
        System.out.println("contract");
    }
}
//Rent.java
package com.bkms.demo03;

public interface Rent {
    void rent();
    void contract();
}
//ProxyInvocationHandler.java
package com.bkms.demo03;

import com.bkms.demo02.UserServiceProxy;

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

public class ProxyInvocationHandler implements InvocationHandler {
    private Object target;
    private UserServiceProxy usp = new UserServiceProxy();

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

    /**
     * 处理代理实例上的方法调用并返回结果
     * @param proxy 调用该方法的代理实例
     * @param method 代理实例上的接口方法的实例
     * @param args 接口方法参数阵列
     * @return 从代理实例上的方法调用返回的值
     * @throws Throwable
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    	//add agent code here
    	usp.log(usp.getMethodName(method.getName()));
        return method.invoke(rent,args);
    }

    /**
     * 生成代理对象实例
     * @return
     */
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
    }
}
//Client.java
package com.bkms.demo03;

public class Client {
    public static void main(String[] args) {
        //真实角色
        Host host = new Host();
        //代理角色
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        //工厂生成代理类
        pih.setRent(host);//这里实际上是多态,相当于Rent rent = new Host();
        //获取代理类子类实例
        Rent proxy = (Rent) pih.getProxy();
        //调用
        proxy.rent();
        proxy.contract();
    }
}
  1. 例2
package com.bkms.demo04;

import com.bkms.demo02.UserService;
import com.bkms.demo02.UserServiceImpl;

public class Client {
    public static void main(String[] args) {
        //真是角色
        UserServiceImpl userService = new UserServiceImpl();
        //代理类处理类
        ProxyInvocationHandler handler = new ProxyInvocationHandler();
        //设置代理
        handler.setTarget(userService);
        //动态生成代理类
        UserService proxy = (UserService) handler.getProxy();
        //调用真实角色的方法
        proxy.modify();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

muskfans

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

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

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

打赏作者

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

抵扣说明:

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

余额充值