一、基于注解的IOC配置:
前提:开启注解扫描:
<context:component-scan base-package="cn.itcast"></context:component-scan>
扫描指定包及其子包下的所有的类,如果类上使用了@Component注解,就将该类实例化并装配到IOC容器中。
①、@Component(value="")
:相当于在xml中配置了一个bean。如果不指定value属性,默认bean的id是当前类的类名。首字母小写。
使用衍生注解装配bean(与@Component作用相同,只不过更加语义化)
②、@Controller
:一般用于表现层的注解
③、@Service
:一般用于业务层的注解
④、@Repository
:一般用于持久层的注解
注意:如果注解中有且只有一个属性要赋值时,且名称是value,value在赋值时可以不写。
二、注入数据用的注解:
①、@Autowite
:按照类型进行注入,只能注入bean类型。如果有多个类型匹配,自动将其属性名称accountDao作为id,到容器中去查找相同id的bean
②、@QuaLIfier("accountDao")
:配合@Autowite使用,当按照类型注入,有多个类型匹配时,那么可以配置@Qualifier("accountDao")注解指定id注入bean
③、@Resource(name="accountDao")
:可以直接指定id进行注入 (注意:该注解对应JDK1.9不支持)
④、@Value("张三") @Value(${jdbc.url})
:直接注入或从配置文件注入基本数据类型
三、改变作用域及生命周期相关注解
改变作用域注解:
①、@Scope("prototype")
:多例,不配默认为单例(@Scope("Singleton"))
指定生命周期注解:
①、@PostConstruct
:该注解可以指定一个方法为初始化方法
②、@PreDestroy
:该注解可以指定一个方法为销毁方法
以上两个注解JDK1.9也不支持
四、Spring配置类相关注解(取代applicationContext.xml)
①、@Configuration
:声明配置类
代替applicationContext.xml的作用获取容器时需要使用AnnotationApplicationContext(有@Configuration注解的类.class)。
②、@ComponentScan
:配置注解扫描
作用和在spring的xml配置文件中的:
<context:component-scan base-package="cn.itcast"></context:component-scan>
一致
③、@Bean(name="beanName")
:将方法的返回值装配到IOC容器中
name:给当前@Bean注解方法创建的对象指定一个名称(即bean的id)。
④、@PropertySource(values={"path1","path2"})
:加载外部资源文件
values单独使用可以省略,也可以为数组形式values={}
⑤、@Import(value={config1.class,config2.clsss})
:引入其他配置类
values单独使用可以省略,也可以为数组形式values={}
⑥配置类使用案例:
//JdbcConfig.java
@PropertySource(value = {"classpath:druiddb.properties"})
public class JdbConfig {
@Value("${jdbc.driverClassName}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean(name = "jdbcTemplate")
public JdbcTemplate getJdbcTemplate(@Qualifier("dataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean(name = "dataSource")
public DataSource getDataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driverClassName);
druidDataSource.setUrl(url);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
return druidDataSource;
}
}
//springConfiguration.java
@Configuration
@ComponentScan("com.jingfu") //开启注解扫描
@Import(JdbConfig.class)
public class SpringConfiguration {
//其他配置
}
五、Spring整合junit相关注解
①、@RunWith(value=SpringJUnit4ClassRunner.class)
value单独使用也可以省略,配置SpringJUnit4ClassRunner.class来代替原来junit的运行器
②、@ContextConfiguration(values={},class={})
加载配置类或者xml配置文件
value[]:用来指定xml配置文件
class[]: 用来指定配置类
③ Spring整合junit4使用案例
//替换掉Junit运行器
@RunWith(SpringJUnit4ClassRunner.class)
//加载配置类
@ContextConfiguration(locations={"classpath:applicationContext.xml"})
public class AccountServiceTest {
//按照属性名自动注入service层接口
@Autowire
private IAccountService accountService;
@Test
public void queryAccountList() {
List<Account> accounts = accountService.queryAccountList();
for (Account account : accounts) {
System.out.println(account);
}
}
}
六、Spring AOP相关注解
①、开启注解扫描和注解AOP
<context:component-scan base-package="cn.itcast"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
②、装配类并将此类声明为切面类@Component("logger")
与@Aspect
@Component("logger")
@Aspect //表示当前类是一个切面类(也可以称之为通知类)
public class Logger{}
③、配置通知类型
@Before(value="")
:把当前方法看作前置通知。value:用于指定切入点表达式,还可以指定切入点表达式的引用
@AfterReturning(value="")
:把当前方法看成是后置通知,value属性作用同上
@AfterThrowing(value="")
:把当前方法看成是异常通知,value属性作用同上
@After
:把当前方法看成是最终通知,value属性作用同上
@Around
:把当前方法看成环绕通知,value属性作用同上
@Pointcut:
:指定切入点表达式
通过一个空方法单独配置切入点表达式。在其他通知引用该切入点表达式时通过:方法名称+(),来进行引用。
@Pointcut("execution(* com.jingfu.service.AccountServiceImpl.*(..))")
private void pt1() {}
④、@EnableAspectJAutoProxy
:开启AOP的注解扫描与配置类结合使用
⑤、通过注解配置的切面类使用案例案例
//配置类
package com.jingfu.configuration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration//声明为配置类
@ComponentScan("com.jingfu")//配置注解包扫描
@EnableAspectJAutoProxy//开启Aop的注解扫描
public class applicationConfig {
}
//q切面类
package com.jingfu.log;
@Component("logger")
@Aspect
public class Logger {
@Pointcut("execution(* com.jingfu.service.AccountServiceImpl.*(..))")
private void pt1() {}
//前置通知
@Before("pt1()")
public void beforePrintLog(){
System.out.println("前置通知执行了");
}
//后置通知
@AfterReturning("pt1()")
public void afterReturningPrintLog(){
System.out.println("后置通知执行了");
}
//异常通知
@AfterThrowing("pt1()")
public void afterThrowingPrintLog(){
System.out.println("异常通知执行了");
}
//最终通知
@After("pt1()")
public void afterPrintLog(){
System.out.println("最终通知执行了");
}
/**环绕通知
* spring框架为我们提供了一个借口,该接口可以作为环绕通知的方法参数来使用
* ProceedingJoinPoint 当环绕通知执行时,spring框架会为我们注入该接口的实现类
* 它有一个方法proceed(),就相当于invoke,执行目标方法
*
* spring的环绕通知
* 它是spring为我们提供的一种可以在代码中手动控制增强方法何时执行的方式。
* @param pjp
* @return
*/
@Around("pt1()")
public Object around(ProceedingJoinPoint pjp){
Object object = null;
try {
System.out.println("前置通知");
object = pjp.proceed();
System.out.println("后置通知");
} catch (Throwable e) {
System.out.println("异常通知");
e.printStackTrace();
} finally {
System.out.println("最终通知");
}
return object;
}
}