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: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 {}
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基本一致。
@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 extends Condition>[] value();condition接口中唯一方法:
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);配合@bean,自定义加入容器的条件。
@PostConstruct、@PreDestroy
作用:指定容器中组建的销毁和初始化方法。除了该注解,实现InitializingBean, DisposableBean接口。或者通过@bean时的参数指定,也都可以指定初始化方法。
<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>