2022.5.29 使用java配置spring 与代理模式
9、使用java配置spring
我们现在要完全不使用Spring的xml配置了,全权交给Java来做!
JavaConfig 是Spring的一个子项目,在Spring 4之后,它成为了一个核心功能!
User
1 package com.xing.pojo; 2 3 import org.springframework.beans.factory.annotation.Value; 4 import org.springframework.stereotype.Component; 5 6 //这里这个注解的意思,就是说明这个类被Spring接管了,注册到了容器中 7 @Component 8 public class User { 9 private String name; 10 11 public String getName() { 12 return name; 13 } 14 15 @Value("小明") 16 public void setName(String name) { 17 this.name = name; 18 } 19 20 @Override 21 public String toString() { 22 return "User{" + 23 "name='" + name + '\'' + 24 '}'; 25 } 26 }
MyConfig2
1 package com.xing.config; 2 3 import org.springframework.context.annotation.Configuration; 4 5 @Configuration 6 public class MyConfig2 { 7 8 }
MyConfig
1 package com.xing.config; 2 3 import com.xing.pojo.User; 4 import org.springframework.context.annotation.Bean; 5 import org.springframework.context.annotation.ComponentScan; 6 import org.springframework.context.annotation.Configuration; 7 import org.springframework.context.annotation.Import; 8 9 //Configuration代表这是一个配置类,就和我们之前看的beans.xmL一样 10 //这个也会被Spring容器托管,注册到容器中,因为他本来就是一个@Component 11 @Configuration 12 @ComponentScan("com.xing.pojo") //扫描包 13 @Import(MyConfig2.class) //相当于合并另一个配置文件 14 public class MyConfig { 15 16 //注册一个bean .就相当于我们之前写的一个bean标签 17 //这个方法的名字,就相当了 bean标签中的id属性 18 //这个方法的返回值。就相当bean标签中的cLass属性 19 20 21 @Bean 22 public User getUser() { 23 return new User();//就是返回要注入到bean的对象! 24 25 } 26 }
test
1 import com.xing.config.MyConfig; 2 import com.xing.pojo.User; 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.annotation.AnnotationConfigApplicationContext; 5 6 public class MyTest { 7 public static void main(String[] args) { 8 //纯注解方式 9 //如果完全使用了配置类方式去做,我们就只能通过 AnnotationConfig 上下文来获取容器,通过配置类的cLass对象加载! 10 ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); 11 // 参数为Bean注解下的方法名 12 User getUser = (User) context.getBean("getUser"); 13 System.out.println(getUser.getName()); 14 } 15 }
10、代理模式
为什么要学习代理模式?因为这就是SpringAOP的底层!【SpringAOP和SpringMvC】
代理模式的分类:
-
静态代理
-
动态代理
10.1、静态代理
角色分析:
-
抽象角色:一般会使用接口或者抽象类来解决
-
真实角色︰被代理的角色
-
代理角色︰代理真实角色,代理真实角色后,我们一般会做一些附属操作
-
客户:访问代理对象的人!
代码步骤:
1.接口
1 package com.xing.demo01; 2 3 //租房: 4 public interface Zufang { 5 void rent(); 6 }
2.真实角色
1 package com.xing.demo01; 2 3 //房东:真实角色 4 public class Fangdong implements Zufang{ 5 @Override 6 public void rent() { 7 System.out.println("房东出租房子"); 8 } 9 10 }
3.代理角色
1 package com.xing.demo01; 2 3 public class Zhongjie implements Zufang{ 4 private Fangdong fangdong; 5 6 public Zhongjie() { 7 } 8 9 public Zhongjie(Fangdong fangdong) { 10 this.fangdong = fangdong; 11 } 12 13 @Override 14 public void rent() { 15 seeHouse(); 16 fangdong.rent(); 17 fare(); 18 } 19 20 public void seeHouse() { 21 System.out.println("中介带你看房"); 22 } 23 public void fare() { 24 System.out.println("收中介费"); 25 } 26 }
4.客户端访问代理角色
1 package com.xing.demo01; 2 3 //租客(我): 4 public class Zuke { 5 public static void main(String[] args) { 6 Fangdong fangdong = new Fangdong(); 7 8 //代理,//代理,中介帮房东租房子,但是呢?代理角色一般会有一些附属操作!│ 9 Zhongjie zhongjie = new Zhongjie(fangdong); 10 //你不用面对房东,直接找中介租房即可 11 zhongjie.rent(); 12 } 13 }
代理模式的好处:
-
可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
-
公共也就就交给代理角色!实现了业务的分工!
-
公共业务发生扩展的时候,方便集中管理!
缺点:
-
一个真实角色就会产生一个代理角色;代码量会翻倍,开发效率会变低~
练习
在调用每个业务的前面增加一个日志,表明使用了什么业务(不修改原来代码(真实角色与业务的代码)增加代理,在代理中修改代码)
业务
1 package com.xing.demo02; 2 3 public interface UserService { 4 void add(); 5 void delete(); 6 void update(); 7 void query(); 8 9 }
真实角色
1 package com.xing.demo02; 2 3 public class UserServiceImpl implements UserService{ 4 @Override 5 public void add() { 6 System.out.println("增加一个用户"); 7 } 8 9 @Override 10 public void delete() { 11 System.out.println("删除一个用户"); 12 } 13 14 @Override 15 public void update() { 16 System.out.println("修改一个用户"); 17 } 18 19 @Override 20 public void query() { 21 System.out.println("查询一个用户"); 22 } 23 }
代理角色
1 package com.xing.demo02; 2 3 public class UserServiceProxy implements UserService{ 4 private UserServiceImpl userService; 5 6 public void setUserService(UserServiceImpl userService) { 7 this.userService = userService; 8 } 9 10 @Override 11 public void add() { 12 log("add"); 13 userService.add(); 14 } 15 16 @Override 17 public void delete() { 18 log("delete"); 19 userService.delete(); 20 } 21 22 @Override 23 public void update() { 24 log("update"); 25 userService.update(); 26 } 27 28 @Override 29 public void query() { 30 log("query"); 31 userService.query(); 32 } 33 34 //日志方法 35 public void log(String msg){ 36 System.out.println("使用了"+msg+"方法"); 37 } 38 39 }
客户端访问
1 package com.xing.demo02; 2 3 public class Client { 4 public static void main(String[] args) { 5 UserServiceImpl userService = new UserServiceImpl(); 6 7 UserServiceProxy proxy = new UserServiceProxy(); 8 //代理真实角色 9 proxy.setUserService(userService); 10 proxy.add(); 11 proxy.query(); 12 13 } 14 }
AOP:
10.2、动态代理
-
动态代理和静态代理角色一样
-
动态代理的代理类是动态生成的,不是我们直接写好的!
-
动态代理分为两大类:基于接口的动态代理,基于类的动态代理。
-
基于接口---JDK动态代理
-
基于类:cglib
-
java字节码实现 : javasist
-
需要了解两个类: Proxy:代理,InvocationHandler:调用处理程序
UserService
1 package com.xing.demo04; 2 3 public interface UserService { 4 void add(); 5 void delete(); 6 void update(); 7 void query(); 8 9 }
UserServiceImpl
1 package com.xing.demo04; 2 3 public class UserServiceImpl implements UserService { 4 @Override 5 public void add() { 6 System.out.println("增加一个用户"); 7 } 8 9 @Override 10 public void delete() { 11 System.out.println("删除一个用户"); 12 } 13 14 @Override 15 public void update() { 16 System.out.println("修改一个用户"); 17 } 18 19 @Override 20 public void query() { 21 System.out.println("查询一个用户"); 22 } 23 }
ProxyInvocationHandler
1 package com.xing.demo04; 2 3 import com.xing.demo03.Rent; 4 5 import java.lang.reflect.InvocationHandler; 6 import java.lang.reflect.Method; 7 import java.lang.reflect.Proxy; 8 9 //等我们会用这个类,自动生成代理类! 继承一个接口 10 public class ProxyInvocationHandler implements InvocationHandler { 11 12 //被代理的接口 13 private Object target; 14 15 public void setTarget(Object target) { 16 this.target = target; 17 } 18 19 //生成得到代理类 20 public Object getProxy() { 21 return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this); 22 } 23 24 @Override 25 //处理代理实例,并返回结果 26 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 27 //动态代理的本质就是使用反射机制实现 28 log(method.getName());//method.getName()得到方法的名字 29 Object result = method.invoke(target, args); 30 return result; 31 } 32 33 public void log(String msg) { 34 System.out.println("执行了" + msg + "方法"); 35 } 36 }
Client
1 package com.xing.demo04; 2 3 public class Client { 4 public static void main(String[] args) { 5 //真实角色 6 UserServiceImpl userService = new UserServiceImpl(); 7 //代理角色 8 ProxyInvocationHandler pih = new ProxyInvocationHandler(); 9 10 pih.setTarget(userService);//设置要代理的对象 11 12 //动态生成代理类 13 UserService proxy = (UserService) pih.getProxy(); 14 15 proxy.add(); 16 proxy.delete(); 17 } 18 }
如果实现别的实现类,只需修改Client中的真实角色就可
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!