ホームページ  >  記事  >  バックエンド開発  >  Javaプログラミング構成の考え方を詳しく解説 - JavaEEチュートリアル

Javaプログラミング構成の考え方を詳しく解説 - JavaEEチュートリアル

不言
不言オリジナル
2018-03-30 10:35:371631ブラウズ

この記事では主に Java プログラミング構成のアイデアについて詳しく説明します。

Java プログラミング構成のアイデアについて詳しく説明します

SpringBoot は開発に役立つ多くの優れたスターターを提供します。実稼働環境の特殊性により、プログラムの制御性を向上させるためにデフォルトの統合構成をカスタマイズする必要がありますが、構成は公式のスターターより優れているわけではありません。先週は仕事と装飾の関係でブログが正常に更新できなかったので、更新を止めると怠けてしまうのではないかと思い、少し時間を割いて比較的簡単な記事を書きました。後ほど、装飾初心者から始めるまでの私の経験についてお話します。

テクノロジー: 構成、ComponentScan、PropertySource、EnableTransactionManagement、Bean、Value
: 記事には構成コードのみが掲載されており、完全なテストコードは github にあります。
ソースコード:https://github.com/ITDragonBl...
記事のディレクトリ構造:

Javaプログラミング構成の考え方を詳しく解説 - JavaEEチュートリアル

1. Java プログラミング構成

Spring 4.x より前の、アプリケーションは通常 XML 構成を使用し、ビジネス ロジックではアノテーションを使用することをお勧めします。しかし、Spring 4.x 以降、当局は XML 設定ではなく Java プログラミング設定を使用することを推奨し始めました。これはなぜでしょうか。これら 2 つの構成の長所と短所は何ですか?

Java プログラミング構成と XML 構成

Xml 構成の利点: 私たち古い世代のプログラマー (┬_┬) にとって、XML は非常に使いやすく、使いやすく、拡張しやすく、アプリケーション構成パラメーターを変更するために再コンパイルする必要がありません。

XML 構成の欠点: 構成ファイルの読み取りと解析には時間がかかり、内容が多すぎる XML 構成ファイルは肥大化し、管理が不便になります。

Java プログラミング構成の利点: XML 構成と比較して、その構造はより明確で読みやすく、XML の解析時間も節約されます。

Java プログラミング構成の欠点: アプリケーション構成パラメーターを変更するには再コンパイルが必要です。実際、実際の運用環境では、アプリケーションの構成が完了した後は、一般にそれを自由に変更することはありません。

Spring 4.x と Spring Boot の両方が Java プログラミング構成の使用を推奨していることを考慮すると、これを使用する必要はありませんが、理解する必要があります。

Java プログラミング構成手順

最初のステップ: 構成クラスを作成し、クラス名にアノテーション Configuration を追加し、これが構成クラスであることを Spring に通知し、その機能は XML ファイルに似ています

2 番目のステップ: ロードクラス内の外部構成ファイル 注釈 PropertySource を名前に追加し、プロパティ ファイルの読み取りパスを指定します

ステップ 3: アプリケーション構成属性値を取得し、注釈 Value を属性変数に追加し、パラメータを取得します${} 式を使用して構成ファイルを作成します

ステップ 4: 依存性注入の場合、メソッドに Bean アノテーションを追加するか、FactoryBean を使用できます

最初と 4 番目のステップの構文は、2 番目で詳しく紹介します記事の一部。 2 番目と 3 番目のステップの構文については、この記事の 3 番目の部分で詳しく説明します。

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());
    }

}

Transaction クラス

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 を参照してください

2. コンポーネントの注入

Bean アノテーションは、XML ファイルの 60e23eb984d18edbb092da6b8f295aba标签,其中被Bean注解修饰的方法名对应60e23eb984d18edbb092da6b8f295aba タグの ID に似ています。 Beanアノテーションのvalue属性。 SpringBoot の基礎となるコードで広く使用されています。

コンテナの起動後にオブジェクトを作成し、使用後にコンテナから直接取得したい場合は、何もする必要はありません。Spring のデフォルトは単一のインスタンスであるためです。つまり、オブジェクトはインスタンスの後に作成されます。コンテナが起動され、コンテナに保存され、コンテナから再度使用されます。

コンテナの起動後にオブジェクトを作成するのではなく、使用時にオブジェクトを作成してコンテナに保存し、次回使用するときにコンテナから取得するようにしたい場合、これは遅延読み込みによって実現できます。つまり、Lazy アノテーションで変更されます。

コンテナの起動後にオブジェクトが作成されるのではなく、使用されるたびにオブジェクトが作成されることを希望する場合は、マルチインスタンス メソッドを使用します。つまり、Scope アノテーションを使用します。パラメータの値は次のとおりです。プロトタイプ、つまり @Scope("prototype")。

コンテナの起動後に条件に基づいて注入する必要があるBeanを選択したい場合は、SpringBootの基になる評価でこのアノテーションを使用するかどうかを判断するためにConditionalアノテーションを使用できます。

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则为单例
    }

}

3. プロパティの割り当て

プロパティの割り当て手順:

ステップ 1: アノテーション 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[&#39;java.version&#39;]}") // 系统配置: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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。