Spring

Spring框架总结

Spring是一个轻量级的容器,它的核心是 IoC(控制反转) 和 AOP(面向切面编程)

IoC 控制反转

将对象的创建权限交给Spring管理,通过Spring容器获取对象的方式被成为控制反转

  • 基于 XML 方式
<bean id="userService" class="com.qikux.service.impl.UserServiceImpl" /> 
  • 基于注解方式

# @Controller : 将控制层对象交给 Spring管理
# @Service    : 将业务层对象交给 Spring管理
# @Repository : 将持久层对象交给 Spring管理
# @Component : 将 其他层对象交给 Spring管理 ,例如 切面 

@Service
public class UserServiceImpl implement UserService{
    ...
}

Spring容器需要使用注解进行IoC, 那么需要启用扫描指定的包 <context:component-scan />

  • 基于 JavaConfig
# @Configuration : 标记一个类是 配置 类 ,使用 @Bean 管理 对象 

@Configuration
public class RootConfig {
    
    @Bean 
    public UserService userService() {
        return new UserServiceImpl() ;
    }
}

DI 依赖注入

给 Spring 管理的对象的属性 自动注入值的过程 被称为 依赖注入

实现方式

  • 属性注入
  • 构造注入
  • 静态工厂注入
  • 实例工厂注入
属性注入

要求Spring管理的对象,需要提供无参构造方法、需要提供 set方法 (注解除外)
相对比较灵活

  1. 基于 xml 的注入方式
<bean id="userDao" class="com.qikux.dao.impl.UserDaoImpl" />

<bean id="userService" class="com.qikux.service.impl.UserServiceImpl">
    <property name="userDao" ref="userDao">
</bean> 
  1. 基于 注解 的注入方式
@Service
public class UserServiceImpl implement UserService{
    
    private UserDao userDao ; 
    
    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao ;
    }
}

  1. 基于 JavaConfig的注入方式
@Configuration
public class RootConfig {
    
    @Bean 
    public UserService userService(UserDao userDao) {
        return new UserServiceImpl(userDao) ; 
    }
}
不同数据类性 的注入方式
  • 字面量 (基本数据类型 + 包装类 + 字符串)
  1. xml方式
<property name="age" value="10">

通过 value 属性 注入, name=“age” 中的 age 指定的是 对象中的 setAge 方法对应的属性

  1. 注解注入
@Value("10")
@Value("${age}")

${age} 代表 从 properties 配置中读取的值

  • 引用bean
  1. xml方式
<property name="userDao" ref="userDao">

通过 ref 引用一个 Spring管理的对象的BeanId

  1. 注解注入 (要求掌握三个注入的使用区别)
  • @Autowired : (这个注解是属业spring的)根据类型注入Spring管理的某个对象,默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如果容器中类型有多个,会产生异常,可以配置@Qualifier 指定 注入的bean名称

  • @Resource : 这个注解属于J2EE的) 默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

  • @Injected : 是 JSR-330 规范提供的依赖包 (javax.inject), 按.照类型注入,可以通过@Named 指定注入的 bean名称
    三者区别可以参考@Autowired、@Inject、@Resource三者区别

  • List集合

<property name="list">
    <list>
        <value /> | <ref />
    </list>
</property>
  • Set 集合

和 List集合用法相同,只需要把 list标签 换成 set 标签即可

  • 数组

和 List集合用法相同,只需要把 list标签 换成 array 标签即可

  • Map 集合
<property name="map">
    <map>
        <entry key="" value="" value-type=""></entry>
    </map>
</property>

entry 中属性有 key, key-ref, value , value-ref, value-type

  • Properties 注入
<property name="attrs">
    <props>
        <prop key="email">huo@qq.com</prop>
    </props>
</property>

  • Null 注入
<property name="xxx">
    <null />
</property>
  • 特殊字符注入
<property name="xxx">
    <value><![CDATA[特殊字符]]></value>
</property>
构造注入

必须提供有参构造,根据有参构造,完成对象的属性赋值
不是很灵活,但适用于 一成不变 的对象, 可以尽可能保证某个属性必须存在值

  1. XML注入
<bean id="userDao" class="com.qikux.dao.impl.UserDaoImpl" />

<bean id="userService" class="com.qikux.service.impl.UserServiceImpl">
     <constructor-arg name="id" value="2" />
</bean> 

constructor-arg 标签中有 index , name, value , ref, type 等属性

  1. 注解注入
@Service
public class UserServiceImpl implement UserService{
    
    private UserDao userDao ; 
    
    @Autowired
    public  UserServiceImpl(UserDao userDao) {
        this.userDao = userDao ;
    }
}

构造注入 只能使用 @Autowired 注解 ,如果一个类中有且只有一个构造方法(有参),那么可以省略 @Autowired

静态工厂注入
<bean id="user" class="com.qikux.factory.UserFactory" factory-method="getUser" />

getUser 是 UserFactory中的静态方法,且返回一个 User方法, getUser方法不能有任何参数

实例工厂注入

<bean id="factory" class="com.qikux.factory.UserFactory" />

<bean id="user" factory-bean="factory" factory-method="getUser" />

getUser 是 UserFactory中的实例方法,且返回一个 User方法, getUser方法不能有任何参数

AOP

面向切面编程、是对面向对象的扩展和补充,通过横切的方式向目标对象的某个切点织入逻辑
AOP的实现手段是通过 动态代理,默认采用 JDK动态代理,也可以使用 cglib 动态代理

好处

在不修改原有代码的基础上,对程序进行增强,是一种无侵入式的编程方式

能做什么 ?

  • 事务管理
  • 日志记录
  • 性能检测

实现方式

  • advice

  • aspectj

依赖 jar

aspectjwearver

aspectjrt
Advice
  • MethodBeforeAdvice : 前置通知
  • AfterReturningAdvice : 后置通知
  • MethodInterceptor : 环绕通知
  • ThrowsAdvice : 异常抛出增强
使用 Aspectj 配置 Advice
  • 基于 XML 的配置
  1. 使用 aop 命名空间,启用 aspectj 自动代理
<aop:aspectj-autoproxy />

默认采用JDK动态代理,可以设置 proxy-target-class 属性为 true, 启用 cglib 代理

  1. 将 切面类 交给 Spring管理
<bean id="logAspect" class="....." />
  1. 将 切面类 ,通过 切点表达式 绑定到 目标对象上
 <aop:config>
    <aop:pointcut id="pt" expression="execution(....)"/>
    <aop:advisor advice-ref="logAspect" pointcut-ref="pt" />
</aop:config>
Aspectj 实现切面
  • 基于 XML 的配置
  1. 编写一个 增强类
public class LogAspectj {
    
    public void before(JointPoint jp) {
        ...
    }
}
  1. 配置 增强类
<bean id="logAspect" class="....." />
  1. 使用 aop 命名空间,启用 aspectj 自动代理
<aop:aspectj-autoproxy />

4.将 切面类 ,通过 切点表达式 绑定到 目标对象上

<aop:config>
    <aop:aspect ref="logAspect">
        <aop:pointcut id="pt" expression="execution(....)"/>
        <aop:before method="before" pointcut-ref="pt"" />
    </aop:aspect>
</aop:config>
  • 基于注解的配置
    • @Before : 前置通知
    • @AfterReturning : 后置通知
    • @Around : 环绕通知
    • AfterThrowing : 异常抛出通知

@Before , @AfterReturning, @AfterThrowing 注释的方法第一个参数都可以住 JoinPoint 对象
@Around 注释的方法 可以注入一个 @ProceedingJoinPoint, 方法必须返回 Object

  1. 编写一个增强类
@Aspect
@Component
public class LogAspectj {
    
    @Before("execution(....)")
    public void before(JointPoint jp) {
        ...
    }
}

  1. 启用 自动代理
<aop:aspectj-autoproxy />
  • 基于 JavaConfig 的配置
  1. 配置类上,启用自动代理

@EnableAspectJAutoProxy

  1. 配置切面类
@Aspect
@Component
public class LogAspectj {
    
    @Before("execution(....)")
    public void before(JointPoint jp) {
        ...
    }
}

Spring 整合 MyBatis

环境:spring-orm.jar, mybatis.jar , mysql-connector-java.jar, mybatis-spring.jar , druid.jar

  • XML 配置
  1. 读取 properties配置文件
<context:property-placeholder file-encoding="utf-8" 
        location="classpath:jdbc.properties" 
        local-override="true"/>
  1. 配置 数据源
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="..."></property>
    <property name="url" value="..."></property>
    <property name="username" value="..."></property>
    <property name="password" value="..."></property>
</bean>
  1. 配置 SqlSessionFactory
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
    <property name="dataSource" ref="dataSource"/>
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
    <property name="mapperLocations" value="classpath*:com/**/mapper/*.xml"/>
</bean>
  1. 扫描 持久层接口 MapperScannerConfigurer
<mybatis:scan base-package="com.qikux.dao" />
  • JavaConfig 的配置
@Configuration
@PropertySource("classpath:jdbc.properties")
@MapperScan("com.qikux.dao")
public class MyBatisAutoConfig {

    @Autowired
    private Environment env ;
    /**
     * 配置数据源
     * @return
     */
    @Bean("dataSource")
    @Profile("dev") // 默认环境是  default
    public DataSource dataSource_dev() {
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(env.getProperty("db.driver"));
        ds.setUrl(env.getProperty("db.url"));
        ds.setUsername(env.getProperty("db.username"));
        ds.setPassword(env.getProperty("db.password"));
        ds.setMaxActive(Integer.valueOf(env.getProperty("db.maxActive")));
        return ds ;
    }


    @Bean("dataSource")
    @Profile("pro")
    public DataSource dataSource_pro() {
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(env.getProperty("pro.db.driver"));
        ds.setUrl(env.getProperty("pro.db.url"));
        ds.setUsername(env.getProperty("pro.db.username"));
        ds.setPassword(env.getProperty("pro.db.password"));
        ds.setMaxActive(Integer.valueOf(env.getProperty("pro.db.maxActive")));
        return ds ;
    }

    /**
     *  配置 SqlSessionFactory
     */
    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        // 创建一个 SqlSessionFactoryBean 对象
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        // 整合 数据源
        bean.setDataSource(dataSource);
        // 整合 mybatis配置文件
        // 读取 classpath下 某一个配置文件
        bean.setConfigLocation(new ClassPathResource("/mybatis-config.xml"));

        // 批量读取 classpath下的资源文件
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources("classpath*:com/**/mapper/*.xml");
        // 整合 映射文件
        bean.setMapperLocations(resources);

        return bean.getObject() ;
    }

}

Spring 配置事务管理

  • XML的配置
  1. 配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
    <property name="dataSource" ref="dataSource"></property>
</bean>
  1. 配置 事务切面
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="query*" propagation="SUPPORTS" isolation="READ_COMMITTED" read-only="true"
                    rollback-for="java.lang.Throwable"/>
        <tx:method name="*" rollback-for="java.lang.Throwable" />
    </tx:attributes>
</tx:advice>

  1. 配置 切入点
<aop:config>
    <aop:pointcut id="pt" expression="execution(* com.qikux.service..*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
</aop:config>
  • 基于注解的配置
  1. 配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
    <property name="dataSource" ref="dataSource"></property>
</bean>
  1. 启用事务注解支持
<tx:annotation-driven transaction-manager="transactionManager"/>
  1. 在业务层类/方法上,添加 @Transactional 注解
  • JavaConfig的配置
  1. 配置类的编写
@Configuration
@EnableTransactionManagement
public class TransactionAutoConfig {

    @Resource
    private DataSource dataSource ;

    @Bean
    public TransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource) ;
    }
}

2.在业务层类/方法上,添加 @Transactional 注解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值