Spring注解驱动开发
自动装配
@Resource
特点:可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;
不同点:没有能支持@Primary功能没有支持@Autowired(reqiured=false);
@Resource(name="bookDao2")
private BookDao bookDao;
@Inject
特点:需要导入javax.inject的包,和Autowired的功能一样。
不同点:没有required=false的功能
@Inject
private BookDao bookDao;
@Autowired
@Autowired可以标注的位置:
1)标注在方法位置:Spring容器创建当前对象,就会调用方法,完成赋值。(@Bean+方法参数;参数从容器中获取;默认不写@Autowired效果是一样的,都能自动装配)
@Bean
public Color color(Car car){
Color color = new Color();
color.setCar(car);
return color;
}
@Autowired
//标注在方法,Spring容器创建当前对象,就会调用方法,完成赋值;
//方法使用的参数,自定义类型的值从ioc容器中获取
public void setCar(Car car) {
this.car = car;
}
2)标在构造器上:如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取
@Autowired
public Boss(Car car){
this.car = car;
System.out.println("Boss...有参构造器");
}
3)放在参数位置:spring容器自动完成参数的注入
public Boss(@Autowired Car car){
this.car = car;
System.out.println("Boss...有参构造器");
}
@Autowired、@Resource和@Inject的区别
1、@Autowired是Spring定义的
2、@Resource和@Inject都是java规范
Aware注入Spring底层组件
自定义组件想要使用Spring容器底层的一些组件 ,例如ApplicationContext,BeanFactory的等,可以通过实现xxxAware接口,Spring容器在创建对象的时候,会调用接口规定的方法注入相关组件。
@Component
public class Red implements ApplicationContextAware,BeanNameAware,EmbeddedValueResolverAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// TODO Auto-generated method stub
System.out.println("传入的ioc:"+applicationContext);
this.applicationContext = applicationContext;
}
@Override
public void setBeanName(String name) {
// TODO Auto-generated method stub
System.out.println("当前bean的名字:"+name);
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
// TODO Auto-generated method stub
String resolveStringValue = resolver.resolveStringValue("你好 ${os.name} 我是 #{20*18}");
System.out.println("解析的字符串:"+resolveStringValue);
}
}
@profile
Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能
特点:
1)加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境
2)写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
3)没有标注环境标识的bean在,任何环境下都是加载的;
@PropertySource("classpath:/dbconfig.properties")
@Configuration
public class MainConfigOfProfile implements EmbeddedValueResolverAware{
@Value("${db.user}")
private String user;
private StringValueResolver valueResolver;
private String driverClass;
@Bean
public Yellow yellow(){
return new Yellow();
}
@Profile("test")
@Bean("testDataSource")
public DataSource dataSourceTest(@Value("${db.password}")String pwd) throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Profile("dev")
@Bean("devDataSource")
public DataSource dataSourceDev(@Value("${db.password}")String pwd) throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/ssm_crud");
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Profile("prod")
@Bean("prodDataSource")
public DataSource dataSourceProd(@Value("${db.password}")String pwd) throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/scw_0515");
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
// TODO Auto-generated method stub
this.valueResolver = resolver;
driverClass = valueResolver.resolveStringValue("${db.driverClass}");
}
}
AOP
步骤:
1、导入aop模块;Spring AOP:(spring-aspects)
2、定义一个业务逻辑类(MathCalculator);在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)
3、定义一个日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行;
4、通知方法:
前置通知(@Before):logStart:在目标方法(div)运行之前运行
后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)
返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行
异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行
环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
5、给切面类的目标方法标注何时何地运行(通知注解);
6、将切面类和业务逻辑类(目标方法所在类)都加入到容器中;
7、必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
8、给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】
在Spring中很多的 @EnableXXX;
/**
* 切面类
* @Aspect: 告诉Spring当前类是一个切面类
*/
@Aspect
public class LogAspects {
//抽取公共的切入点表达式
//1、本类引用
//2、其他的切面引用
@Pointcut("execution(public int com.atguigu.aop.MathCalculator.*(..))")
public void pointCut(){};
//@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
@Before("pointCut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+Arrays.asList(args)+"}");
}
@After("com.atguigu.aop.LogAspects.pointCut()")
public void logEnd(JoinPoint joinPoint){
System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
}
//JoinPoint一定要出现在参数表的第一位
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
}
@AfterThrowing(value="pointCut()",throwing="exception")
public void logException(JoinPoint joinPoint,Exception exception){
System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息:{"+exception+"}");
}
}
AOP底层原理
1、@EnableAspectJAutoProxy注解
调用@Import(AspectJAutoProxyRegistrar.class):给容器中导入AspectJAutoProxyRegistrar,利用AspectJAutoProxyRegistrar自定义给容器中注册bean,给容器中注册一个AnnotationAwareAspectJAutoProxyCreator对象
2、AnnotationAwareAspectJAutoProxyCreator的继承与实现关系
3、创建和注册AnnotationAwareAspectJAutoProxyCreator
4、AnnotationAwareAspectJAutoProxyCreator作为后置处理器的作用
总结
声明式事务
环境搭建
1、导入相关依赖
数据源、数据库驱动、Spring-jdbc模块
2、配置数据源
JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据
3、给方法上标注 @Transactional 表示当前方法是一个事务方法;
4、 @EnableTransactionManagement 开启基于注解的事务管理功能;
5、配置事务管理器来控制事务;
@Bean
public PlatformTransactionManager transactionManager()