Spring注解编程

Spring多文件配置处理

# 非web环境
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext-*.xml");

# web环境

  	contextConfigLocation
		classpath:applicationContext-*.xml
# applicationContext.xml 整合其他配置内容



 ...
# 非web环境
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");

# web环境

  	contextConfigLocation
		classpath:applicationContext.xml

接口的契约性

注解的契约性

Spring的基础注解

在Spring框架应用注解时,如果对注解配置的内容不满意,可以通过Spring配置文件进行覆盖。

》》》搭建开发环境


》》》对象相关注解

1)@Component: 替换原有Spring配置文件中bean标签

显示指定工厂创建对象的id值:@Component("u");

Spring配置文件覆盖注解配置内容:

2)@Component的衍生注解

以下三种注解能更加准确的表达一个类型的作用

@Repository ===》XXXDAO

@Service ===》XXXService

@Controller


注意:①本质上这些衍生注解就是@Component,作用、细节、用法完全一致

②Spring整合MyBatis开发过程中,不使用@Repository、@Component,原因是DAO的对象是动态代理创建的

3)@Scope: 控制简单对象创建次数

注意:不添加@Scope Spring提供默认值singleton

4) @Lazy:延迟创建单实例对象

注意:使用@Lazy注解后,Spring使用这个对象的时候,才会进行对象的创建

5)生命周期相关注解

》》》@Autowired ===> 用户自定义类型

① @Autowired基于类型进行注入:注入对象的类型,必须与目标成员变量类型相同或者是其子类(实现类)===> 推荐


② @Autowired @Qualifier 基于名字进行注入

③ @Autowired放置位置

a) 放置在对应成员变量的set方法上

b) 放置在成员变量之上,Spring通过反射直接对成员变量进行注入(赋值)===> 推荐

④JavaEE规范中类似功能的注解

JSR250 @Resource(name="userDAOImpl")基于名字进行注入

@Autowired()

@Qualifier("userDAOImpl")

注意:如果在应用Resource注解时,名字没有配对成功,那么会继续按照类型进行注入

JSR330 @Inject作用 @Autowired完全一致 基于类型进行注入 ===> EJB3.0


  javax.inject
  javax.inject
  1

》》》JDK类型

1)@Value注解

①不能应用在静态成员变量上,否则赋值(注入)失败

②该注解+Properties这种方式,不能注入集合类型,YMAL/YML配置方式替代

2)@PropertySource

# 当前包及其子包

》》》排除方式

》》》包含方式

》》》配置互通

》》》注解和配置文件使用的条件

程序员自己开发的类型,可以加入对应的注解,进行对象创建。

非程序员开发的类型,需要配置文件(bean标签来完成)进行配置。(如:SqlSessionFactoryBean、MapperScannerConfigure)

SSM半注解

Spring的高级注解

@Configuration实际上是@Component的衍生注解

》》》配置日志

基于注解开发,不能集成log4j, 发现没有日志打印

基于注解开发,集成的是logback



  org.slf4j
  slf4j-api
  1.7.25



  org.slf4j
  jcl-over-slf4j
  1.7.25



  ch.qos.logback
  logback-classic
  1.2.3



  ch.qos.logback
  logback-core
  1.2.3



  org.logback-extensions
  logback-ext-spring
  0.1.4

<?xml version="1.0" encoding="UTF-8" ?>

    
        
  					
            %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
        
    

    
        
    

等同于XML配置文件中bean标签

》》》对象的创建

简单对象:直接通过new方式创建的对象

复杂对象:不能通过new方式创建的对象(如:Connection, SqlSessionFactory)

package com.demo;

import com.demo.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

@Configuration
public class AppConfig {

    /**
     * 简单对象
     * @return
     */
    @Bean
    public User user() {
        return new User();
    }

    /**
     * 复杂对象(推荐使用)
     *     Connection不能直接通过new创建
     * @return
     */
    @Bean
    public Connection conn() {
        Connection conn = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://192.168.XXX.222:3306/ssm_db?useSSL=false", "root", "root");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return conn;
    }
}
package com.demo.bean;

import org.springframework.beans.factory.FactoryBean;

import java.sql.Connection;
import java.sql.DriverManager;

public class ConnectionFactoryBean implements FactoryBean {

    @Override
    public Connection getObject() throws Exception {
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://192.168.XXX.222:3306/ssm_db?useSSL=false", "root", "root");

        return conn;
    }

    @Override
    public Class<?> getObjectType() {
        return Connection.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}
/**
     *  遗留系统使用该方式创建
     *      很少自己写ConnectionFactoryBean,来创建复杂对象
     * @return
     */
@Bean
public Connection conn() {
    Connection conn = null;
    try {
        ConnectionFactoryBean factoryBean = new ConnectionFactoryBean();
        conn = factoryBean.getObject();
    } catch (Exception e) {
        e.printStackTrace();
    }

    return conn;
}

》》》自定义id值

@Bean("id")

》》》控制对象创建次数

@Bean

@Scope("singleton|prototype") 默认值singleton

》》》用户自定义注入

package com.demo;

import com.demo.injection.UserDAO;
import com.demo.injection.UserDAOImpl;
import com.demo.injection.UserService;
import com.demo.injection.UserServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean
    public UserDAO userDAO() {
        return new UserDAOImpl();
    }

    @Bean
    public UserService userService(UserDAO userDAO) {
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDAO(userDAO);

        return userService;
    }
}
package com.demo;

import com.demo.injection.UserDAO;
import com.demo.injection.UserDAOImpl;
import com.demo.injection.UserService;
import com.demo.injection.UserServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean
    public UserDAO userDAO() {
        return new UserDAOImpl();
    }

  	// 简化写法(没有把userDAO作为形参传入)
    @Bean
    public UserService userService() {
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDAO(userDAO());

        return userService;
    }
}

》》》JDK类型注入

@Bean
public Customer customer() {
    Customer customer = new Customer();
    // 硬代码 耦合
    customer.setId(1);
    customer.setName("zhangsan");

    return customer;
}
package com.demo;

import com.demo.bean.Customer;
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;

/**
 *  读取配置文件init.properties,解决耦合问题
*/
@Configuration
@PropertySource("classpath:init.properties")
public class AppConfig {
    
    @Value("${id}")
    private Integer id;
    @Value("${name}")
    private String name;

    @Bean
    public Customer customer() {
        Customer customer = new Customer();
        customer.setId(id);
        customer.setName(name);

        return customer;
    }
}

@ComponentScan等同于XML配置文件中的标签

目的:扫描注解 (如:@Component、@Value、@Autowired ...)

》》》排除、包含的使用

1)排除

2)包含

》》》配置优先级

配置文件bean标签 > @Bean > @Component及其衍生注解


优先级高的配置 覆盖 优先级低的配置

配置的优先级能解决耦合问题

ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig4.class, AppConfig5.class);

ApplicationContext ctx = new AnnotationConfigApplicationContext("com.demo.config");

》》》多配置信息整合

① 多个配置Bean的整合


1) base-package进行多个配置Bean的整合

2) @Import

1. 可以创建对象

2. 多配置bean的整合


3) 指定多个配置Bean的Class对象

ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig1.class, AppConfig2.class,...);

② 配置Bean与@Component相关注解的整合

③ 配置Bean与Spring XML配置文件的整合

跨配置的注入

Spring在配置Bean中加入了@Configuration注解后,底层就会通过CGlib的代理方式,来进行对象相关的配置、处理

基于schema

基于特定功能注解 ===> 推荐

基于原始


    

基于@Bean注解 ===> 推荐

package com.demo;

import org.springframework.context.annotation.*;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;

@Configuration
@ComponentScan(basePackages = "com.demo")
public class AppConfig {

    @Bean
    public PropertySourcesPlaceholderConfigurer configurer() {
        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
        configurer.setLocation(new ClassPathResource("init.properties"));

        return configurer;
    }
}

纯注解版AOP编程

package com.demo.aop;

public interface UserService {
    void register();
    void login();
}
package com.demo.aop;

import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {
    @Override
    public void register() {
        System.out.println("UserServiceImpl.register");
    }

    @Override
    public void login() {
        System.out.println("UserServiceImpl.login");
    }
}
package com.demo.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MyAspect {

    @Pointcut("execution(* com.demo.aop..*.*(..))")
    public void pointCut() {}

    @Around("pointCut()")
    public Object arroud(ProceedingJoinPoint joinPoint) throws Throwable {

        System.out.println("-------Log-----------");

        Object proceed = joinPoint.proceed();

        return proceed;
    }
}
package com.demo.aop;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan(basePackages = "com.demo.aop")
@EnableAspectJAutoProxy
public class AOPConfig {
}

》》》注解AOP细节分析

Spring AOP 代理 默认:JDK

SpringBoot AOP 代理默认:CGlib

纯注解版Spring+MyBatis整合

package com.demo.mybatis;

import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import javax.sql.DataSource;
import java.io.IOException;

@Configuration
@ComponentScan(basePackages = "com.demo.mybatis")
@MapperScan(basePackages = "com.demo.mybatis")
public class MyBatisAutoConfiguration {

    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://192.168.30.222:3306/ssm_db");
        dataSource.setUsername("root");
        dataSource.setPassword("root");

        return dataSource;
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();

        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setTypeAliasesPackage("com.demo.mybatis");
//        sqlSessionFactoryBean.setMapperLocations(new ClassPathResource("UserDAOMapper.xml"));
        try {
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            Resource[] resources = resolver.getResources("com/demo/mapper/*Mapper.xml");
            sqlSessionFactoryBean.setMapperLocations(resources);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return sqlSessionFactoryBean;
    }
}
mybatis.driverClassName=com.mysql.cj.jdbc.Driver
mybatis.url=jdbc:mysql://192.168.XXX.222:3306/ssm_db
mybatis.username=root
mybatis.password=root
mybatis.typeAliasesPackages=com.demo.mybatis
mybatis.mapperLocations=com/demo/mapper/*Mapper.xml
package com.demo.mybatis;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

@Data
@Component
@PropertySource("classpath:mybatis.properties")
public class MybatisProperties {
    @Value("${mybatis.driverClassName}")
    private String driverClassName;
    @Value("${mybatis.url}")
    private String url;
    @Value("${mybatis.username}")
    private String username;
    @Value("${mybatis.password}")
    private String password;
    @Value("${mybatis.typeAliasesPackages}")
    private String typeAliasesPackages;
    @Value("${mybatis.mapperLocations}")
    private String mapperLocations;
}
package com.demo.mybatis;

import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import javax.sql.DataSource;
import java.io.IOException;

@Configuration
@ComponentScan(basePackages = "com.demo.mybatis")
@MapperScan(basePackages = "com.demo.mybatis")
public class MyBatisAutoConfiguration {

    @Autowired
    private MybatisProperties mybatisProperties;

    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(mybatisProperties.getDriverClassName());
        dataSource.setUrl(mybatisProperties.getUrl());
        dataSource.setUsername(mybatisProperties.getUsername());
        dataSource.setPassword(mybatisProperties.getPassword());

        return dataSource;
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();

        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setTypeAliasesPackage(mybatisProperties.getTypeAliasesPackages());
//        sqlSessionFactoryBean.setMapperLocations(new ClassPathResource("UserDAOMapper.xml"));
        try {
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            Resource[] resources = resolver.getResources(mybatisProperties.getMapperLocations());
            sqlSessionFactoryBean.setMapperLocations(resources);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return sqlSessionFactoryBean;
    }
}

纯注解版事务编程

package com.demo.mybatis;

public interface UserService {
    void register(User user);
}
package com.demo.mybatis;

import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Data
@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDAO userDAO;

    @Override
    public void register(User user) {
        userDAO.save(user);
    }
}
package com.demo.mybatis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

@Configuration
@EnableTransactionManagement
public class TransactionAutoConfiguration {

    @Autowired
    private DataSource dataSource;

    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager() {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);

        return dataSourceTransactionManager;
    }
}

Spring中YAML/YML使用


  org.yaml
  snakeyaml
  2.0

》》》init.yml

account:
  name: zhangsan
  password: root
package com.demo.yml;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Data
@Component
public class Account {
    @Value("${account.name")
    private String name;
    @Value("${account.password}")
    private String password;
}
package com.demo.yml;

import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;

import java.util.Properties;

@Configuration
@ComponentScan(basePackages = "com.demo.yml")
public class YmlAutoConfiguration {

    @Bean
    public PropertySourcesPlaceholderConfigurer configurer() {
        YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
        yamlPropertiesFactoryBean.setResources(new ClassPathResource("init.yml"));
        Properties properties = yamlPropertiesFactoryBean.getObject();

        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
        configurer.setProperties(properties);

        return configurer;
    }
}

》》》init.yml

account:
  name: zhangsan
  password: root
list: 111,222
package com.demo.yml;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.List;

@Data
@Component
public class Account {
    @Value("${account.name")
    private String name;
    @Value("${account.password}")
    private String password;
    @Value("#{'${list}'.split(',')}")
    private List list;
}
展开阅读全文

页面更新:2024-04-29

标签:注解   赋值   优先级   变量   对象   成员   类型   标签   方式   环境

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top