spring 养吾剑总结

spring 养吾剑总结

ioc/di

1、实例化,注入容器

​ 1)等效于new dao.DbDao(),显然,要求必须有一个public的无参构造方法。

<bean id="dd" class="dao.DbDao">bean>
@Component(value = "svDao") //不指定value,默认为dbDao
public class DbDao {}

2)等效于svDao.getInstance()或DbDaoFactory.getInstance(),即执行一个方法,然后把返回值注入容器。

<bean id="" factory-bean="" factory-method=""/>
<bean id="" class="" factory-method=""/> 
@Bean(name=runner)//注意,该标签修饰方法,但类必须是一个配置类,即被@configuration修饰的类
public QueryRunner createQueryRunner(@qualifier("mysqlds") DataSource dataSouce){
	return new QueryRunner(dataSouce));
}

2、DI注入

​ 构造函数注入:

​ 相当于new DbDao(dataBase,dataUtil…)


    <constructor-arg name="dataBase" ref="db">constructor-arg>
    <constructor-arg name="dataUtil" ref="dU">constructor-arg>
                    
                    
                    
                    
bean>

set方法注入:

<property name="dataBase" ref="db"/>标签属性只有name、value和ref,要求必须有public的set方法

注入集合类型:
property中还可以使用list或map标签注入集合
list标签下使用value标签写具体的集合内容,map标签使用entry标签注入键值对内容

DI注解:(可以写在属性或set方法上,即使属性是私有的)
@Autowired 只要容器中有唯一的一个bean对象且要注入的变量类型一致,就可以注入成功。
如果有没有,报错;如果有多个,则使用变量名为id对容器内对象进行匹配,有则注入,没有报错。可以給属性、构造器、方法进行注解。构造器只有一个参数的情况下,可以省略之。
@Qualifier 和autowired配合使用时指定按照名称注入。在給类成员注入时,不能单独使用。在給方法参数注入时可以。
value属性 可以指定id
@Resource jsr250注解,直接按照id注入,不匹配数据类型 使用name属性指定id。name属性默认值为字段名。

@inject jsr310注解,是@Resource的升级版,可以配合spring的@primary一起使用。

@beans 方法注解,运行该方法,并将方法返回值以方法名为id注入容器。配合@primary注解,可以指定该bean为首选项,使@Autowired多匹配的情况下,不以id进行匹配,而默认选择该首选项。但如果注入时指定了@Qualifier,则以@Qualifier为准。另外,可以通过autowire参数指定自动注入方法参数依赖,该参数需要一个枚举类型:Autowire.NO/BY_NAME/BY_TYPE

3 ioc核心容器的启动方式。

​ 有两种读取配置文件/配置类的启动方式

ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
application ac= new annotationconfigapplicationcontext(springconfiguration.class,jdbcconfig.class

​ 在非web程序中,往往需要我们自己创建容器,前者读取xml文件创建容器,后者读取配置类创建容器。

​ 在web程序中,往往是web程序读取web.xml文件,在创建前端过滤器的过程中,同步创建了ioc容器,一般会根据contextConfigLocation初始化参数以xml创建核心容器(ssm的项目一般以xml文件创建)。

AOP

​ 即方法增强,以某个类中的某个方法增强其他方法。工具类和工具方法被称为通知类,被增强的方法称为切入点,切入点集合被称为切面。

<aop:config>
    //公共的切入点表达式
    <aop:pointcut id="allSeiviceMethod" expression="execution(*htyy.dao.impl.AccountDaoImpl.*(..))"/>
    //使用loggerAdvice类的logger实例(已被ioc管理)进行增强。
    <aop:aspect id="loggerAdvice" ref="logger">
        //使用logger.printLogger方法增强AccountDaoImpl.findAll()方法
        <aop:before method="printLogger" pointcut="execution(* *..AccountDaoImpl.findAll())"/>
        <aop:after method="printLogger" pointcut="execution(* htyy.service.impl.AccountServiceImpl.findAcountById(..))">aop:after>
        <aop:around method="aroundAdvice" pointcut-ref="allSeiviceMethod">aop:around>
    aop:aspect>
aop:config>

通知类型:

        before 前置通知,切入点方法之前执行
        after-returning 后置通知 切入点方法正常return前执行
        after-throwing 错误通知 报错时执行
        after 最终通知 相当于finally
        around 环绕通知 将方法和参数传递給通知方法,通知方法内手动操作。

切入点表达式写法:

​ 访问修饰 返回值 包名.包名.类名.方法名(参数列表)
​ public void service.impl.AccountDaoImpl.findAll()
​ 可省 * .. .(…)
​ 可用*.表示当前包及其之包 * …AccountDaoImpl.findAll()
​ 参数写法:
​ 基本类型int 引用类型全类名java.lang.String
表示任意类型,但必须有参数
​ …有无参数均可
​ 实际开发中,通常定位到业务层实现类下的所有方法:
​ * htyy.utis.
.
(…)

环绕方法写法:

public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
    Object proceed=null;
    try {
       System.out.println("前置通知"+ pjp.getArgs().toString());    
        proceed = pjp.proceed(pjp.getArgs());
       System.out.println("后置通知");
    }catch (Throwable t){
       System.out.println("错误通知");
    }finally {
       System.out.println("最终通知"+ proceed.toString());
    }
    return proceed;
}

注解写法:

@Component
@Aspect//表示当前类是一个切面类
public class Logger {
    @Pointcut("execution(* htyy.dao.impl.AccountDaoImpl.*(..))")
    private  void  serviceAllMethod(JoinPoint jp){}

    @After("execution(* htyy.dao.impl.AccountDaoImpl.findAll())")
    public void printLogger(JoinPoint jp){
        System.out.println("原方法已经被增强!"+new Date().toLocaleString());
    }
    
    @Around("serviceAllMethod()")
    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
        Object proceed=null;
        try {
            System.out.println("前置通知"+ pjp.getArgs().toString());
            proceed = pjp.proceed(pjp.getArgs());
            System.out.println("后置通知");
        }catch (Throwable t){
            System.out.println("错误通知");
        }finally {
            System.out.println("最终通知"+ proceed.toString());
        }
        return proceed;
    }
}

通知方法中可以有一个JoinPoint参数,该参数有以下方法
1、getClass 获取当前被增强的类。
2、getSignature().getName()获取到被增强方法的名字。
3、getArgs() 得到当前方法参数。

tips:

  • 使用注解配置会造成固有缺陷,最终通知会在后置、异常之前执行。

  • xml对同一个方法进行增强,按顺序执行。

  • 注解对同一个方法进行增强,倒叙执行。

【声明式事务管理】


<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
        <property name="dataSource" ref="dataSource">property>
bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
         <tx:method name="*" propagation="REQUIRED" read-only="false"/>
	    <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
    tx:attributes>
tx:advice>
//普通方法不需要事务,以find开头的方法需要。   
<aop:config>
        
        <aop:pointcut id="pt1" expression="execution(* com.zty.service.impl.*.*(..))">aop:pointcut>
        
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1">aop:advisor>
aop:config>

​ 注解:

@Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
//如果方法需要的传播和只读不同,可以在方法上单独配。需要在xml中开启注解事务扫描
public class AccountServiceImpl implements IAccountService {}

jdbctemplate

List<Account> accounts = jt.query("select * from account where name like ?", new BeanPropertyRowMapper<Account>(Account.class),name);
jt.update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());

使用方法和dbutils基本一致。

全注解配置spring

@Configuration
    作用: 用于指定当前类是一个spring配置类,当创建容器时会从该类上加载注解。@Configuration 标记了@Component元注解,因此可以被@ComponentScan扫描并处理,在Spring容器初始化时Configuration类 会被注册到Bean容器中,最后还会实例化。
@ComponentScan
    作用: 用于通过注解指定Spring在创建容器时要扫描的包,显然它也能扫到@Configuration注解。
@Bean
    作用: 该注解只能写在方法上,表明使用此方法创建一个对象,并且放入spring容器
    属性: name 用于指定bean的id  默认值是当前方法的名称
@Import
	   作用: 用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration注解。当然,写上也没问题。spring4以后可以直接填一个class数组,注入这些class的bean到容器。特别地,如果填写的是ImportSelector或ImportBeanDefinitionRegistrar接口的实现类,可以自定义进行导入。
 	   属性: value[]:用于指定其他配置类的字节码。 
@Value
	作用:相当于标签的value属性,可以在组建实例化时給字段进行赋值。可以使用spel表达式,例如#{12-32},配合下面的@PropertySource,还可以使用$(person.name)的方式,读取配置文件的值。
@PropertySource
  作用:用于加载.properties文件中的配置,配合@bean使用,将实例注入容器时会搜寻实例属性是否加载了@values注解,如果加载,就回读取配置文件进行赋值。
      例如我们配置数据源时,可以把连接数据库的信息写到properties配置文件中,
      就可以使用此注解指定properties配置文件的位置
@Conditional
	作用:Class[] value();condition接口中唯一方法:
	boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);配合@bean,自定义加入容器的条件。
@PostConstruct、@PreDestroy
	作用:指定容器中组建的销毁和初始化方法。除了该注解,实现InitializingBean, DisposableBean接口。或者通过@bean时的参数指定,也都可以指定初始化方法。

【xml整体配置和maven全包】


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">
    <context:component-scan base-package="">context:component-scan>//开启注解扫描
    <aop:aspectj-autoproxy>aop:aspectj-autoproxy> //开启注解扫描aop
    <tx:annotation-driven transaction-manager="transactionManager">tx:annotation-driven>//开启注解扫描事务管理器
    <import resource="classpath:spring/spring-dao.xml">import>//导入其他springxml
    <context:property-placeholder location="classpath:dbConfig.properties">	context:property-placeholder>//读取properties文件,可用${url}方式调用。
		<dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>5.0.2.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-testartifactId>
            <version>5.0.2.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-jdbcartifactId>
            <version>5.0.2.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-txartifactId>
            <version>5.0.2.RELEASEversion>
        dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-ormartifactId>
      <version>5.0.2.RELEASEversion>
    dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-aopartifactId>
            <version>5.0.2.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.aspectjgroupId>
            <artifactId>aspectjweaverartifactId>
            <version>1.8.7version>
        dependency>
        
        <dependency>
            <groupId>commons-dbutilsgroupId>
            <artifactId>commons-dbutilsartifactId>
            <version>1.4version>
        dependency>
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
        dependency>
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>8.0.13version>
        dependency>
        <dependency>
            <groupId>c3p0groupId>
            <artifactId>c3p0artifactId>
            <version>0.9.1.2version>
        dependency>
    
        <dependency>
            <groupId>cglibgroupId>
            <artifactId>cglibartifactId>
            <version>2.1_3version>
        dependency>

你可能感兴趣的:(spring 养吾剑总结)