本篇文章主要給大家分享了關於Java編程配置思路的詳解,希望對於學習Java的朋友有所幫助
SpringBoot雖然提供了很多優秀的starter幫助我們快速開發,可實際生產環境的特殊性,我們依然需要對預設整合配置做自訂操作,提高程式的可控性,雖然你配的不一定比官方提供的starter好。上週因為工作和裝修的事情,導致博客沒有正常更新,害怕停更會讓人懶惰起來,擠了一點時間寫了一篇內容比較簡單的文章。後面閒聊一下我是如何從裝潢小白到入門的經驗。
技術:Configuration,ComponentScan,PropertySource,EnableTransactionManagement,Bean,Value
##說明:文中只貼出了設定程式碼,完整的測試程式碼在github上。
原始碼:https://github.com/ITDragonBl...#文章目錄結構:
##一、Java程式設定
Java程式設定與xml設定
xml設定缺點:設定檔的讀取和解析需要耗時,xml設定檔內容太多會顯得很臃腫,不方便管理。
Java程式設定優點:相對於xml設定而言,其結構更清晰,可讀性更高,同時也節省了解析xml耗時。
Java程式設定缺點:修改應用程式設定參數需要重新編譯。其實不是一個大的問題,實際生成環境中,應用程式配置完成後一般都不會也不敢去隨意修改。
兩者各有千秋,考慮到Spring4.x和SpringBoot都在推薦使用Java編程配置的方式,那我們也應該順應時代潮流,你可以不用,但你應該要懂!
Java程式設定步驟
第二步:載入外部設定文件,在類別名稱上新增註解PropertySource,指定properties檔案的讀取路徑
#第三步:取得應用程式配置屬性值,在屬性變數上新增註解Value,通過${}表達式取得設定檔中參數
第四步:依賴注入,在方法上加入Bean註解,也可以用FactoryBean
第一步與第四步驟的語法,文章第二部分會詳細介紹。第二步和第三步的文法,文章第三部分會詳細介紹。
import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import com.mchange.v2.c3p0.ComboPooledDataSource; /** * Spring 配置类 * 配置数据源,事务管理,bean,自动扫描包 * @author itdragon */ @Configuration // 声明该类为配置类 @PropertySource({"classpath:propertySource.properties"}) // 引入外部文件 @ComponentScan("com.itdragon") // 配置自动扫描包的路径 @EnableTransactionManagement // 开启基于注解的事务管理功能 public class ApplicationContextConfig { @Value("${DATA_USER}") private String DATA_USER; @Value("${DATA_PAWD}") private String DATA_PAWD; @Value("${DATA_DRIVER}") private String DATA_DRIVER; @Value("${DATA_JDBC_URL}") private String DATA_JDBC_URL; @Bean // 数据源 public DataSource dataSource() throws Exception{ ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(DATA_USER); dataSource.setPassword(DATA_PAWD); dataSource.setDriverClass(DATA_DRIVER); dataSource.setJdbcUrl(DATA_JDBC_URL); return dataSource; } @Bean // jdbc模板 public JdbcTemplate jdbcTemplate() throws Exception{ JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource()); return jdbcTemplate; } @Bean // 事务管理 public PlatformTransactionManager transactionManager() throws Exception{ return new DataSourceTransactionManager(dataSource()); } }
事務類別
import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.itdragon.dao.ITDragonDao; @Service public class ITDragonServer { @Autowired(required=false) private ITDragonDao itdragonDao; public List<Map<String,Object>> findAll() { return itdragonDao.findAll(); } @Transactional public void updateNameById(String name, Long id) { itdragonDao.updateUserNameById(name, id); System.out.println(0/0); // 事务异常 } }
完整程式碼,請非同步github
二、元件注入
標籤,其中被Bean註解修飾的方法名稱對應60e23eb984d18edbb092da6b8f295aba
標籤中的id,也可以透過Bean註解的value屬性來設定id的值。在SpringBoot底層程式碼中被大量使用。 若希望容器啟動後創建對象,並在使用後從容器中直接獲取,則什麼都不需要做,因為Spring默認是單實例,即容器啟動後創建對象,並保存到容器中,使用時再從容器中取得。
若希望容器啟動後不創建對象,而是在使用時再創建,繼而保存到容器中,下次使用再從容器中獲取,可以通過懶加載的方式實現,即使用Lazy註解修飾。
若希望容器啟動後不創建對象,而是在每次使用時創建,則採用多實例的方式,即使用Scope註解,參數的值為prototype,即@Scope("prototype") 。
若希望容器啟動後根據條件選擇需要注入的Bean,可以使用註解Conditional判斷,SpringBoot的底層打量使用了此註解。
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Controller; import com.itdragon.entity.ITDragonEntity; import com.itdragon.server.ITDragonServer; /** * 知识点二:配置自动扫描包路径 * 一、注解ComponentScan的value值设置自动扫描包的路径 * 二、注解ComponentScan的excludeFilters值设置扫描排除的规则 * 1)、通过注解@Filter设置排除的类型,type=ANNOTATION表示按照注解包含排除。classes是具体的注解,如Controller,Server,Repository * 三、注解ComponentScan的includeFilters值设置扫描加入的规则 * 1)、通过设置useDefaultFilters=false关闭Spring默认扫描全部的功能,使includeFilters生效 * * 知识点三:@Filter常用的拦截类型 * 一、FilterType.ANNOTATION:按照注解 * 二、FilterType.ASSIGNABLE_TYPE:按照给定的类型,包括其子类和实现类 * 三、FilterType.CUSTOM:使用自定义规则 * * 第一个ComponentScan注解表示在指定包下不扫描通过Controller注解修饰的类和ITDragonServer类及其子类和实现类 * 第二个ComponentScan注解表示在指定包下只扫描通过Controller注解修饰的类 * 第三个ComponentScan注解表示在指定包下根据自定义拦截规则,不扫描满足规则的类 */ @Configuration @ComponentScan(value="com.itdragon",excludeFilters={@Filter(type=FilterType.ANNOTATION,classes={Controller.class}), @Filter(type=FilterType.ASSIGNABLE_TYPE,classes={ITDragonServer.class})}) //@ComponentScan(value="com.itdragon",includeFilters={@Filter(type=FilterType.ANNOTATION,classes={Controller.class})},useDefaultFilters=false) //@ComponentScan(value="com.itdragon",excludeFilters={@Filter(type=FilterType.CUSTOM,classes={ITDragonCustomTypeFilter.class})}) public class ITDragonConfig { /** * 知识点一:配置bean * 一、注解Bean的value值表示bean的id * 二、注解Bean的value值未设置,则方法名表示bean的id */ @Bean(value="itdragonBean") public ITDragonEntity itdragonEntity() { //方法名很重要,类似xml的id名,也可以通过@bean的value值重定义 return new ITDragonEntity("itdragon", "configuration-password", 25); } /** * 知识点四:Scope属性 * @Scope,调整作用域,默认单实例 * singleton:单实例:ioc容器启动后创建对象放到ioc容器中,需要是从容器中获取。 * prototype:多实例:ioc容器启动后每次获取对象时都要创建对象。 * request:同一次请求创建一个实例 * session:同一个session创建一个实例 * * 知识点五:懒加载 * 针对单实例而言,在容器启动后不创建对象,在第一次使用Bean时创建对象。可以理解为单实例的一种补充。 * */ // @Scope("prototype") @Lazy @Bean public ITDragonEntity scopeTopicBean() { System.out.println("^^^^^^^^^^^^^^^^^^^^^Create Bean"); return new ITDragonEntity("scopeBean", "singleton-prototype-request-session", 25); } /** * 知识点六:Conditional条件判断 * 满足条件才会注册bean,可以修饰在类上,管理整个类下的组件注入。 */ @Bean @Conditional({ITDragonCustomCondition.class}) public ITDragonEntity conditionalBean() { return new ITDragonEntity("conditionalBean", "Conditional-Condition-CustomCondition", 25); } /** * 知识点七:FactoryBean工厂Bean * FactoryBean默认通过调用getObject创建的对象,通过调用isSingleton设置单实例和多实例。 */ @Bean public ITDragonFactoryBean itdragonFactoryBean() { return new ITDragonFactoryBean(); } }
自訂的條件判斷元件注入類別
import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; /** * 自定义的条件判断组件注入 * @author itdragon * */ public class ITDragonCustomCondition implements Condition{ /** * 判断注册的bean中是否含有指定的bean */ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // 获取bean的注册类 BeanDefinitionRegistry registry = context.getRegistry(); return registry.containsBeanDefinition("scopeTopicBean"); // 有则加载conditionalBean } }
自訂Bean的工廠類別
import org.springframework.beans.factory.FactoryBean; import com.itdragon.entity.ITDragonEntity; /** * 自定义Bean的工厂类 * @author itdragon * */ public class ITDragonFactoryBean implements FactoryBean<ITDragonEntity>{ public ITDragonEntity getObject() throws Exception { System.out.println("^^^^^^^^^^^^^^^^^^^^^FactoryBean Create Bean"); return new ITDragonEntity(); // 创建对象并返回到容器中 } public Class<?> getObjectType() { return ITDragonEntity.class; } public boolean isSingleton() { return false; // 设置多实例,true则为单例 } }
三、屬性賦值
第一步:透過註解PropertySource引入外部文件。可以引入多個,若擔心檔案不存在,可以透過參數ignoreResourceNotFound設定忽略
第二步:透過註解Value從外部檔案取得值,一般採用${}格式,也支援#{} SpEL表達式,也可以直接傳字串。如果想要接收一些複雜的數值,例如集合,可以考慮使用註解ConfigurationProperties,後續會詳細介紹兩者的優缺點。
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import com.itdragon.entity.ITDragonEntity; /** * 知识点一: 引入外部文件,并从文件中获取值 * @PropertySource 引入外部文件,支持多个,如果文件不存在会报错,可以通过设置参数ignoreResourceNotFound=true忽略 * @Value 从外部文件中获取值,支持spel表达式,#{},${},string * @author itdragon */ @Configuration @PropertySource(value={"classpath:propertySource.properties","classpth:xxx.properties"},ignoreResourceNotFound=true) public class ITDragonConfigValue { @Value("${ACCOUNT}") // 从配置文件获取数据 private String ACCOUNT; @Value("${PASSWORD}") private String PASSWORD; @Value("${AGE}") private Integer AGE; @Value("ITDragon") // 普通赋值 private String str; @Value("#{(1+2-3)/4*5}") // 算术运算 private String operator; @Value("#{1>2 || 2 <= 3}") // 关系运算 private Boolean comparison; @Value("#{systemProperties['java.version']}") // 系统配置:os.name private String systemProperties; @Value("#{T(java.lang.Math).abs(-18)}") // 表达式 private String mapExpression; @Bean("valueBean") public ITDragonEntity itdragonEntity() { System.out.println("^^^^^^^^^^^^^^^^^^^^ str : " + str); System.out.println("^^^^^^^^^^^^^^^^^^^^ operator : " + operator); System.out.println("^^^^^^^^^^^^^^^^^^^^ comparison : " + comparison); System.out.println("^^^^^^^^^^^^^^^^^^^^ systemProperties : " + systemProperties); System.out.println("^^^^^^^^^^^^^^^^^^^^ mapExpression : " + mapExpression); return new ITDragonEntity(ACCOUNT, PASSWORD, AGE); } }
这里并不是介绍如何学习一门技术,而是论养成一个学习习惯的重要性。大一时期,因为担心找不到工作而报了一个线上培训机构。经常被洗脑,其中一句话而我印象深刻 ---- "让优秀成为一种习惯"。听得我热血沸腾。花了五六千大洋报名,后来才发现网上有免费的。。。。个人不建议参加培训。
这钱花的还算值得,"让优秀成为一种习惯",这句话对我的影响很大,从大学到工作,每当遇到陌生的知识,并没有选择逃避它。而是抽时间从网上找资料,去学习,整理,实践直到弄懂它。可我万万没有想到,这种学习的精神竟然用到了装修上。。。。可能学习已经是我的一个习惯了吧!
开始,我是一个装修小白,不知道什么是全包、半包、清包;不知道什么是硬装、软装;也不知道装修的流程;不知道水电线、橱柜、洁具的品牌选择,不知道挂机、柜机、风管机、中央空调的优缺点;不知道封阳台的利弊;更不知道一个装修效果图要七八千。面对这些未知的领域,我寸步难行。我清楚的知道:如果你不懂,你就是砧板上的鱼肉,任人宰割。
现在,我通过在百度,知乎,兔巴兔等平台上找答案,并把内容用Markdown的格式整理!我都被自己吓到了。不仅如此,我还在抢设计师的饭碗,自己动手设计效果图。在制作效果图的过程中,发现了很多不合理的设想。庆幸问自己设计了一套效果图,不然又有很多无用功,耗时,耗力,耗钱。爸妈和女票就是客户,而我就一直处于改!改!改!的阶段。体验了一把前端工程师的辛酸。
我是谁?我在哪?我在做什么?
我是一名程序员,我在学习的道路上,我在做能提高自己的事情!
相关推荐:
以上是Java程式配置思路詳解- JavaEE教程的詳細內容。更多資訊請關注PHP中文網其他相關文章!