一、概述 Spring注解开发。
二、常用注解 @Configuration 标记在类上,告诉Spring这是一个配置类
1 2 3 4 5 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext (MainConfig.class);@Configuration public class MainConfig {}
@ComponentScan 标记在类上,告诉Spring扫描哪些包下的类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 @Configuration @ComponentScans( value = { @ComponentScan(value="com.imalt",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 MainConfig { @Bean("person") public Person person01 () { return new Person ("lisi" , 20 ); } } public class MyTypeFilter implements TypeFilter { @Override 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 ; } return false ; } }
@controller 标记在类上,这些类纳入进spring容器中进行管理。内部用@Component,一般用在控制层。
1 2 3 4 5 6 7 8 9 10 11 12 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller { String value () default "" ; }
@service 标记在类上,这些类纳入进spring容器中进行管理。内部用@Component,一般用在服务层。
1 2 3 4 5 6 7 8 9 10 11 12 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Service { String value () default "" ; }
@repository 标记在类上,这些类纳入进spring容器中进行管理。内部用@Component,一般用在数据层。
1 2 3 4 5 6 7 8 9 10 11 12 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Repository { String value () default "" ; }
@component 标记在类上,这些类纳入进spring容器中进行管理。一般标记普通组件。
1 2 3 4 5 6 7 8 9 10 11 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Component { String value () default "" ; }
@Bean 给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id。
@Scope 调整作用域
@Lazy 懒加载
@Import 快速给容器中导入一个组件,springboot底层大量使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 @Configuration @Import({Color.class,Red.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class}) public class MainConfig2 { @Scope("prototype") @Lazy @Bean("person") public Person person () { System.out.println("给容器中添加Person...." ); return new Person ("张三" , 25 ); } } public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String []{"com.atguigu.bean.Blue" ,"com.atguigu.bean.Yellow" }; } } public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @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){ RootBeanDefinition beanDefinition = new RootBeanDefinition (RainBow.class); registry.registerBeanDefinition("rainBow" , beanDefinition); } } }
@Conditional 满足一定条件bean才会装配。标记在类上时,表示类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效。springboot底层大量使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @Conditional({LinuxCondition.class}) @Configuration public class MainConfig2 {} ---- public class LinuxCondition implements Condition { @Override public boolean matches (ConditionContext context, AnnotatedTypeMetadata metadata) { ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); ClassLoader classLoader = context.getClassLoader(); Environment environment = context.getEnvironment(); BeanDefinitionRegistry registry = context.getRegistry(); String property = environment.getProperty("os.name" ); boolean definition = registry.containsBeanDefinition("person" ); if (property.contains("linux" )){ return true ; } return false ; } }
@Autowired Bean 自动装配注解。
@Resource Bean 自动装配注解。可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的; 没有能支持@Primary功能没有支持@Autowired(reqiured=false)。
@Inject Bean 自动装配注解。需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;* @Autowired:Spring定义的; @Resource、@Inject都是java规范。
@Profile Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 @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) { this .valueResolver = resolver; driverClass = valueResolver.resolveStringValue("${db.driverClass}" ); } }
三、核心 Spring给容器添加组件
1、@ComponentScan 包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类]
2、@Bean[导入的第三方包里面的组件]
3、@Import[快速给容器中导入一个组件]
@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名(Color.class,Red.class)
ImportSelector接口的实现类,返回需要导入的组件的全类名数组(MyImportSelector.class)
ImportBeanDefinitionRegistrar接口的实现类,调用BeanDefinitionRegistry.registerBeanDefinition(“rainBow”, beanDefinition)手动注册bean到容器中
4、用Spring提供的 FactoryBean(工厂Bean)
(1).默认获取到的是工厂bean调用getObject创建的对象
(2).要获取工厂Bean本身,我们需要给id前面加一个&
Spring生命周期 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
Spring自动装配 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 @Configuration @ComponentScan({"com.atguigu.service","com.atguigu.dao", "com.atguigu.controller","com.atguigu.bean"}) public class MainConifgOfAutowired { @Primary @Bean("bookDao2") public BookDao bookDao () { BookDao bookDao = new BookDao (); bookDao.setLable("2" ); return bookDao; } @Bean public Color color (Car car) { Color color = new Color (); color.setCar(car); return color; } }
SpringAOP
@EnableAspectJAutoProxy: 标记再配置类上,启动Aspect.
@Aspect :告诉spring,哪个类是切面类
@Before:前置通知
@After:后置通知
@AfterReturning:返回通知
@AfterThrowing:异常通知
@Around:环绕通知
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 @EnableAspectJAutoProxy @Configuration public class MainConfigOfAOP { @Bean public MathCalculator calculator () { return new MathCalculator (); } @Bean public LogAspects logAspects () { return new LogAspects (); } }
Spring声明式事务
@EnableTransactionManagement:开启基于注解的事务管理功能
@Transactional:表示当前方法是一个事务方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 /** * 声明式事务: * * 环境搭建: * 1、导入相关依赖 * 数据源、数据库驱动、Spring-jdbc模块 * 2、配置数据源、JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据 * 3、给方法上标注 @Transactional 表示当前方法是一个事务方法; * 4、 @EnableTransactionManagement 开启基于注解的事务管理功能; * @EnableXXX * 5、配置事务管理器来控制事务; * @Bean * public PlatformTransactionManager transactionManager() * * * 原理: * 1)、@EnableTransactionManagement * 利用TransactionManagementConfigurationSelector给容器中会导入组件 * 导入两个组件 * AutoProxyRegistrar * ProxyTransactionManagementConfiguration * 2)、AutoProxyRegistrar(implements ImportBeanDefinitionRegistrar): * 给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件; * InfrastructureAdvisorAutoProxyCreator:? * 利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用; * * 3)、ProxyTransactionManagementConfiguration 做了什么? * 1、给容器中注册事务增强器; * 1)、事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解 * 2)、事务拦截器: * TransactionInterceptor;保存了事务属性信息,事务管理器; * 他是一个 MethodInterceptor; * 在目标方法执行的时候; * 执行拦截器链; * 事务拦截器: * 1)、先获取事务相关的属性 * 2)、再获取PlatformTransactionManager,如果事先没有添加指定任何transactionmanger * 最终会从容器中按照类型获取一个PlatformTransactionManager; * 3)、执行目标方法 * 如果异常,获取到事务管理器,利用事务管理回滚操作; * 如果正常,利用事务管理器,提交事务 * */ @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{ //Spring对@Configuration类会特殊处理;给容器中加组件的方法,多次调用都只是从容器中找组件 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource()); return jdbcTemplate; } //注册事务管理器在容器中 @Bean public PlatformTransactionManager transactionManager() throws Exception{ return new DataSourceTransactionManager(dataSource()); } }
Spring容器创建流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
Spring 扩展原理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 @ComponentScan("com.atguigu.ext") @Configuration public class ExtConfig { @Bean public Blue blue () { return new Blue (); } }