文章目录
1.配置类注解
@Configuration: 配置类注解,等同于配置文件,告诉Spring这是一个配置类
@Configuration
public class MainConfig {
}
2.包扫描注解
@ComponentScan:包扫描注解
value
:指定要扫描的包excludeFilters = Filter[]
:指定扫描的时候按照什么规则排除那些组件includeFilters = Filter[]
:指定扫描的时候只需要包含哪些组件
@Filter:包扫描过滤注解
classes
: 过滤的类、注解或者自定义过滤器FilterType.ANNOTATION
:按照注解FilterType.ASSIGNABLE_TYPE
:按照给定的类型;FilterType.ASPECTJ
:使用ASPECTJ表达式FilterType.REGEX
:使用正则指定FilterType.CUSTOM
:使用自定义规则
@ComponentScans(
value = {
@ComponentScan(
value = "com.xiao7",
includeFilters = {
@Filter(
type = FilterType.ANNOTATION,
classes = {Controller.class}),
@Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = {BookService.class}),
@Filter(
type = FilterType.CUSTOM,
classes = {MyTypeFilter.class})
},
useDefaultFilters = false)
})
扫描规则过滤:
public class MyTypeFilter implements TypeFilter {
/**
* metadataReader:读取到的当前正在扫描的类的信息
* metadataReaderFactory:可以获取到其他任何类信息的
*/
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
//获取当前类注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类的路径)
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
System.out.println("--->"+className);
if(className.contains("er")){
return true; //返回true表示过滤掉,不扫描注册
}
return false;
}
}
3.容器中注册组件注解
@Bean:给容器中注册一个Bean
, id
默认是用方法名作为id
value
:指定Bean
的id
initMethod
: 指定初始化方法destroyMethod
: 指定销毁方法
@Scope:调整作用域:
-
prototype
:多实例的,每次获取的时候才会调用方法创建对象 -
singleton
:单实例的(默认值),每次获取就是直接从容器中拿 -
request
:同一次请求创建一个实例 session:同一个session创建一个实例
@Lazy:懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化;
@Scope("prototype")
@Lazy
@Bean("person")
public Person person01(){
return new Person("lisi", 20);
}
@Controller:控制层注解
@Service:业务层注解
@Repositor:仓储层注解
@Component:组件注解
@Import:快速给容器中导入一个组件,可以选择导入
Class
:直接导入类ImportSelector
:自定义逻辑返回需要导入的组件,返回需要导入的组件的全类名数组ImportBeanDefinitionRegistrar
:手动注册bean到容器中
使用注解:
@Import({Color.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {
}
自定义导入:
//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {
//返回值,就是到导入到容器中的组件全类名
//AnnotationMetadata:当前标注@Import注解的类的所有注解信息
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// TODO Auto-generated method stub
//importingClassMetadata
//方法不要返回null值
importingClassMetadata.getAnnotationTypes();
return new String[]{"com.atguigu.bean.Blue","com.atguigu.bean.Yellow"};
}
}
手动导入:
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* AnnotationMetadata:当前类的注解信息
* BeanDefinitionRegistry:BeanDefinition注册类;
* 把所有需要添加到容器中的bean;调用
* BeanDefinitionRegistry.registerBeanDefinition手工注册进来
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean definition = registry.containsBeanDefinition("com.atguigu.bean.Red");
boolean definition2 = registry.containsBeanDefinition("com.atguigu.bean.Blue");
if(definition && definition2){
//指定Bean定义信息;(Bean的类型,Bean。。。)
RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
//注册一个Bean,指定bean名
registry.registerBeanDefinition("rainBow", beanDefinition);
}
}
}
@Conditional:按照一定的条件进行判断,满足条件给容器中注册bean
@Conditional(LinuxCondition.class)
@Bean("linus")
public Person person() {
return new Person("linus", 48);
}
条件类:
//判断是否linux系统
public class LinuxCondition implements Condition {
/**
* ConditionContext:判断条件能使用的上下文(环境)
* AnnotatedTypeMetadata:注释信息
*/
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// TODO是否linux系统
//1、能获取到ioc使用的beanfactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//2、获取类加载器
ClassLoader classLoader = context.getClassLoader();
//3、获取当前环境信息
Environment environment = context.getEnvironment();
//4、获取到bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
String property = environment.getProperty("os.name");
//可以判断容器中的bean注册情况,也可以给容器中注册bean
boolean definition = registry.containsBeanDefinition("person");
if(property.contains("linux")){
return true;
}
return false;
}
}
4.属性加载类注解
@PropertySource:读取外部配置文件中的k/v保存到运行的环境变量中
@Value:加载完外部的配置文件以后使用${}取出配置文件的值
@PropertySource(value={"classpath:/person.properties"})
@Configuration
public class MainConfigOfPropertyValues {
@Value("${db.user}")
private String user;
@Bean
public Person person(){
return new Person();
}
}
@Profile:满足该激活环境时配置
- 使用命令行动态参数: 在虚拟机参数位置加载
-Dspring.profiles.active=dev
- 代码的方式激活某种环境
- 在
springBoot
配置文件中spring.profiles.active=dev
@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;
}
5.监听器和后置处理器
ApplicationListener监听器
ApplicationListener
:实现接口注册时间监听器
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
//当容器中发布此事件以后,方法触发
@Override
public void onApplicationEvent(ApplicationEvent event) {
// TODO Auto-generated method stub
System.out.println("收到事件:"+event);
}
}
@EventListener:监听某个时间的发布
@Service
public class UserService {
@EventListener(classes={ApplicationEvent.class})
public void listen(ApplicationEvent event){
System.out.println("UserService。。监听到的事件:"+event);
}
}
发布事件:
@Test
public void test01(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ExtConfig.class);
//发布事件;
applicationContext.publishEvent(new ApplicationEvent(new String("我发布的时间")) {
});
applicationContext.close();
}
ApplicationListener
:监听器可以监听spring
容器的不同时间的事件
spring
容器的可实现监听器:
springBoot
容器的可实现监听器:
PostProcessor 后置处理器
- BeanPostProcessor: 在Bean的初始化前后进行处理工作
- BeanFactoryPostProcessor:Bean工厂的后置处理器
- BeanDefinitionRegistryPostProcessor:Bean的定义注册后置处理器
BeanPostProcessor
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
return bean;
}
}
BeanFactoryPostProcessor
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("MyBeanFactoryPostProcessor...postProcessBeanFactory...");
int count = beanFactory.getBeanDefinitionCount();
String[] names = beanFactory.getBeanDefinitionNames();
System.out.println("当前BeanFactory中有"+count+" 个Bean");
System.out.println(Arrays.asList(names));
}
}
BeanDefinitionRegistryPostProcessor
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor{
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// TODO Auto-generated method stub
System.out.println("MyBeanDefinitionRegistryPostProcessor...bean的数量:"+beanFactory.getBeanDefinitionCount());
}
//BeanDefinitionRegistry Bean定义信息的保存中心,以后BeanFactory就是按照BeanDefinitionRegistry里面保存的每一个bean定义信息创建bean实例;
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// TODO Auto-generated method stub
System.out.println("postProcessBeanDefinitionRegistry...bean的数量:"+registry.getBeanDefinitionCount());
//RootBeanDefinition beanDefinition = new RootBeanDefinition(Blue.class);
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Blue.class).getBeanDefinition();
registry.registerBeanDefinition("hello", beanDefinition);
}
}
6.事务支持注解
@EnableTransactionManagement:开启spring的事务支持
- 实际是使用Import注册了
TransactionManagementConfiguration
- 默认是
Proxy
,可设置adviceMode
注册AspectJ
事务管理配置类
@EnableTransactionManagement
@ComponentScan("com.atguigu.tx")
@Configuration
public class TxConfig {
//数据源
@Bean
public DataSource dataSource() throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("123456");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate() throws Exception{
return new JdbcTemplate(dataSource());
}
//注册事务管理器在容器中
@Bean
public PlatformTransactionManager transactionManager() throws Exception{
return new DataSourceTransactionManager(dataSource());
}
}
@Transactional:事务注解
propagation
:指定事务的传播行为, 默认:Propagation.REQUIREDisolation
:指定事务的隔离级别,默认:Isolation.DEFAULT,使用数据库的隔离级别rollbackForClassName
:指定事务回滚的捕捉异常,默认:RuntimeExpection运行时异常
使用事务:
@Service
public class UserService {
@Autowired
private UserDao userDao;
@Transactional
public void insertUser(){
userDao.insert();
System.out.println("插入完成...");
// int i = 10/0;
}
}
7.Aop切面注解
@EnableAspectJAutoProxy:开启Aop
切面支持
@Aspect: 告诉Spring当前类是一个切面类
@Pointcut:切点匹配
-
execution():用于匹配方法执行的连接点
例子:
execution(public * *(..))
定义任意公共方法的执行
execution(* set*(..))
定义任何一个以"set"开始的方法的执行
execution(* com.xyz.service.AccountService.*(..))
定义AccountService 接口的任意方法的执行
execution(* com.xyz.service.*.*(..))
定义在service包里的任意方法的执行
execution(* com.xyz.service ..*.*(..))
定义在service包和所有子包里的任意类的任意方法的执行
execution(* com.test.spring.aop.pointcutexp…JoinPointObjP2.*(…))
定义在pointcutexp包和所有子包里的JoinPointObjP2类的任意方法的执行: -
args(): 用于匹配当前执行的方法传入的参数为指定类型的执行方法
例子:
args(String)
参数为String类型(运行时决定)的方法. -
this(): 匹配一个类或者接口的实现类
例子:
this(com.test.spring.aop.pointcutexp.Intf)
实现了Intf接口的所有类,如果Intf不是接口,限定Intf单个类. -
target(): 针对类的匹配条件
例子:
@target(org.springframework.transaction.annotation.Transactional)
带有@Transactional
标注的所有类的任意方法. -
within(): 用于匹配指定类
-
@within():用于匹配所以持有指定注解类的方法
例子:
within(com.test.spring.aop.pointcutexp.*)
pointcutexp包里的任意类.
@within(org.springframework.transaction.annotation.Transactional)
带有@Transactional
标注的所有类的任意方法. -
@args():于匹配当前执行的方法传入的参数持有指定注解的执行
例子:
@args(org.springframework.transaction.annotation.Transactional)
参数带有@Transactional
标注的方法. -
@target():用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解
例子:
@target(org.springframework.transaction.annotation.Transactional)
带有@Transactional
标注的所有类的任意方法. -
@annotation:用于匹配当前执行方法持有指定注解的方法
例子:
@annotation(org.springframework.transaction.annotation.Transactional)
带有@Transactional
标注的任意方法.
@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+"}");
}
}