由配置文件反射提供业务实体

博主从Community Server借鉴方法,用于解决业务实体由多数据库提供或代码移植问题。通过定义数据实体类、多个映射类,在配置文档填入类名,读配置文档反射提供业务实体,客户端调用。移植扩展时,只需改变配置文件type值,可轻松实现。

最近一段时间一直在看Community Server, 从中抄了不少宝到项目里去。

场景: 业务实体由多个不同数据库提供,或是为了方便代码移植到不同数据库上去

借鉴方法: 在CS中采取了从配置文件读取映射类的方法,可以非常灵活的定义数据源。

举例步骤:  1 定义数据实体类User
            public class User:IPeople
          {
                private int _settingID;
                private string _userID;
                private string _userName;
                private string _time;
                 private string _language;
               
                属性:
            }
         
            2 定义多个映射类,对应不同数据库   

             public interface IUserProvider
            {
                  IPeople  GetUserByID(int ID);
                  IPeople  GetNameByID(int ID);
                  IPeople  GetUserByName(string name);
                  .....
            }

            public class UserProviderBySQL:DBHelper,IUserProvider
           {
                  .......
           }

           public class UserProviderByOracle:DBHelper,IUserProvider
           {
                  .......
           }

         3 在配置文档里填入类名
           <?xml version="1.0" encoding="utf-8" ?>
           <root>
           <add name="UserAppDAL" type="AppDAL.UserProviderBySQL"></add>    
          </root>
   
         4 读配置文档然后通过反射来提供业务实体
          

None.gifpublic class ConfigManager
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif           dot.gifdot.gif..
InBlock.gif
InBlock.gif  
public static object GetObjectByName(string name)
ExpandedSubBlockStart.gifContractedSubBlock.gif                   
dot.gif{
InBlock.gif                        XmlDocument d 
= new XmlDocument();
InBlock.gif                        d.Load(filename);
InBlock.gif                        
foreach (XmlNode n in d.SelectSingleNode("root").ChildNodes) 
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                                     
if (n.Attributes["name"].Value == name) 
ExpandedSubBlockStart.gifContractedSubBlock.gif                                     
dot.gif{
InBlock.gif                                     typeStr 
= n.Attributes["type"].Value;
ExpandedSubBlockEnd.gif                                     }

ExpandedSubBlockEnd.gif                          }

InBlock.gif
InBlock.gif                        
if(typeStr == "")
ExpandedSubBlockStart.gifContractedSubBlock.gif                       
dot.gif{
InBlock.gif                                     
throw new TestException("没有找到你要调用的类");
ExpandedSubBlockEnd.gif                        }

InBlock.gif
InBlock.gif                        Type controlType 
= Type.GetType(typeStr,true);     //由反射得到类型
InBlock.gif
                        object obj = Activator.CreateInstance(controlType);
InBlock.gif   
InBlock.gif                         
return obj;
ExpandedSubBlockEnd.gif                 }

InBlock.gif                        
InBlock.gif                  dot.gifdot.gifdot.gif      
InBlock.gif
ExpandedBlockEnd.gif}

None.gif

         5  客户端调用
                  

None.gifpublic class Users
ExpandedBlockStart.gifContractedBlock.gif                 
dot.gif{
InBlock.gif                        dot.gifdot.gifdot.gifdot.gif.
InBlock.gif                       
public static AppDAL.IPeople GetUserByName(string name)
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                                      AppDAL.IPeople  _user 
= null;
InBlock.gif     
InBlock.gif                                      cacheName 
= "nameKey_"+name;
InBlock.gif
InBlock.gif                                      _user 
= ExtendedCache.Get(cacheName) as AppDAL.IPeople; //先查缓存
InBlock.gif
                                      if(_user == null)
ExpandedSubBlockStart.gifContractedSubBlock.gif                                     
dot.gif{
InBlock.gif                                         
//由配置文件得到映射类   
InBlock.gif
                                        IUserProvider _userProvider = 
InBlock.gif                                       ConfigManagerDAL.GetObjectByName (
"UserAppDAL")  as IUserProvider;         
InBlock.gif                                        _user 
= _userProvider.GetUserByName(name);   
InBlock.gif                                        ExtendedCache.Insert(cacheName, _user);
ExpandedSubBlockEnd.gif                                         }

InBlock.gif                                     
return _user;
InBlock.gif
ExpandedSubBlockEnd.gif                       }

InBlock.gif                       dot.gifdot.gif..
ExpandedBlockEnd.gif                 }

None.gif
None.gif

 
          
          6 移植扩展
                只需要改变配置文件中的type值即可更换映射类如
                <add name="UserAppDAL" type="AppDAL.UserProviderByOracle"></add>
                可以轻松实现扩展和移植

转载于:https://www.cnblogs.com/wull66/archive/2005/12/14/296873.html

<think>好的,用户现在想了解反射在实际业务场景中的应用,可能是为了面试准备。我需要结合之前的引用内容,整理出结构清晰的回答,并生成相关问题。首先,我得回忆一下用户提供的引用内容,特别是关于反射的应用场景和实例的部分。引用[1]提到动态代理是反射的典型应用,用于功能扩展如AOP,还有统一处理日志、事务等。引用[2]中用户维护项目时用反射给对象属性赋值,避开了业务逻辑的set方法。引用[3]和[4]讨论了反射结合工厂模式,动态创建子类实例,比如不同的Map实现。这些都是实际的应用场景,需要分点说明。 接下来,我需要组织这些信息,确保每个应用场景都有具体例子,并引用对应的文献。例如,动态代理、对象属性赋值、工厂模式、配置文件解析、框架设计等。每个点都要简明扼要,说明用途和优势,同时附上代码示例,比如工厂模式中使用反射创建实例的代码。然后,生成相关问题。问题需要围绕反射的应用场景、优缺点、性能优化、框架中的应用等,这些都是面试常见问题。确保问题覆盖用户可能关心的方面,帮助用户进一步准备。还要注意回答的结构,使用标题和分段,保持清晰。代码部分用正确的LaTeX格式,行内公式用$...$,独立公式用$$...$$,但这里可能不需要数学公式,主要是代码块。不过用户示例中的Python代码用了代码块,所以Java代码也应该用代码块展示,保持格式一致。 最后,检查引用是否正确,每个引用标识对应正确的文献。例如,动态代理部分引用[^1],属性赋值引用[^2],工厂模式引用[^3][^4]。确保没有遗漏关键点,并且语言口语化,符合用户的中文需求。</think>### 反射在实际业务场景中的应用 #### 1. **动态代理与功能扩展** 反射机制通过动态生成代理类实现**无侵入式功能扩展**,例如: - **AOP(面向切面编程)**:在方法调用前后插入日志记录、事务管理、权限校验等逻辑,无需修改原有代码[^1]。 - **统一处理横切逻辑**:如对接口的所有方法统一添加性能监控逻辑。 ```java // 动态代理示例(基于接口) public class LogProxy implements InvocationHandler { private Object target; public Object bind(Object target) { this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("方法调用前记录日志"); return method.invoke(target, args); } } ``` --- #### 2. **绕过业务逻辑的属性赋值** 当实体类的`set`方法包含业务逻辑时,可通过反射直接操作字段,**避免触发不必要的业务代码**: ```java // 反射赋值示例 public static void setFieldValue(Object obj, String fieldName, Object value) { try { Field field = obj.getClass().getDeclaredField(fieldName); field.setAccessible(true); field.set(obj, value); } catch (Exception e) { e.printStackTrace(); } } ``` *适用场景:DTO转换、批量数据导入等需要绕过业务逻辑的场景[^2]。* --- #### 3. **反射+工厂模式实现灵活扩展** 结合反射与抽象工厂,**动态创建子类实例**,无需修改工厂代码: ```java // 反射工厂示例(根据类名动态创建Map子类) public class MapFactory { public Map<Object, Object> produceMap(String className) { try { Class<?> clazz = Class.forName(className); return (Map<Object, Object>) clazz.newInstance(); } catch (Exception e) { return new HashMap<>(); } } } ``` *优势:新增子类时工厂无需修改,适用于插件化架构、多态场景[^3][^4]。* --- #### 4. **配置文件驱动的对象创建** 通过读取配置文件中的类名,反射实例化对象: ```java // 读取配置示例 String className = config.getProperty("cache.impl"); Cache cache = (Cache) Class.forName(className).newInstance(); ``` *适用场景:策略模式实现、中间件切换(如Redis/Memcached动态选择)。* --- #### 5. **框架设计的核心支撑** - **Spring IoC容器**:通过反射解析`@Autowired`注解完成依赖注入。 - **ORM框架(如MyBatis)**:反射数据库结果集映射到实体类字段。 - **RPC框架(如Dubbo)**:反射调用远程服务方法。 --- ### 面试考察重点 1. **反射的优缺点** - *优点*:灵活性高,支持动态编程。 - *缺点*:性能开销大(可通过缓存`Class`对象优化);破坏封装性。 2. **反射与性能优化** - 缓存`Method`/`Field`对象避免重复查找。 - 使用`setAccessible(true)`跳过安全检查提升速度。 3. **实际应用案例** - 如何用反射实现一个通用JSON解析器? - 如何通过反射绕过单例模式的私有构造方法?(考察安全风险) ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值