ApplicationContext创建方式
//classpath路径下bean.xml
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
//指定路径下bean.xml
ApplicationContext ctx1 = new FileSystemXmlApplicationContext("bean.xml");
//注解驱动 MainConfig配置类
ApplicationContext ctx2 = new AnnotationConfigApplicationContext(MainConfig.class);
@Configuration
Spring配置类标注,等同于xml配置。
@Configuration
public class MainConfig {
}
通过配置@Configuration注解标注的配置类创建ApplicationContext:
ApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);
@Bean
给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id。
等同于:
<bean id="person" class="Person"></bean>
@Configuration
public class MainConfig {
@Bean("person")
public Person person01(){
return new Person("lisi", 20);
}
}
ApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);
//方式一
Person bean = ctx.getBean(Person.class);
//方式二
Person bean2 = ctx.getBean("person");
@ComponentScan
指定要扫描的包,把符合扫描规则的类装配到spring容器中。
属性配置:
basePackages与value: 用于指定包的路径,进行扫描
basePackageClasses: 用于指定某个类的包的路径进行扫描
nameGenerator: bean的名称的生成器
useDefaultFilters: 是否开启对@Component,@Repository,@Service,@Controller的类进行检测
includeFilters: 包含的过滤条件
FilterType.ANNOTATION:按照注解过滤
FilterType.ASSIGNABLE_TYPE:按照给定的类型
FilterType.ASPECTJ:使用ASPECTJ表达式
FilterType.REGEX:正则
FilterType.CUSTOM:自定义规则
excludeFilters: 排除的过滤条件,用法和includeFilters一样
@Configuration
@ComponentScan(value="com.spring",includeFilters={@Filter(type=FilterType.ANNOTATION,classes={Controller.class})},useDefaultFilters=false)
public class MainConfig {
}
等同于:
<context:component-scan base-package="com.spring" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
FilterType.CUSTOM自定义规则:
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();
if(className.contains("er")){
return true;
}
return false;
}
}
@Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class}
@ComponentScans
配置多个@ComponentScan项
@Configuration
@ComponentScans(value = {@ComponentScan(value="com.spring",includeFilters={@Filter(type=FilterType.ANNOTATION,classes={Controller.class})},useDefaultFilters=false) })
public class MainConfig {
}
@Scope
spring中的bean默认是单实例的。
属性
prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象;(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。以后每次获取就是直接从容器(map.get())中拿。(ConfigurableBeanFactory.SCOPE_SINGLETON)
request:同一次请求创建一个实例。(WebApplicationContext.SCOPE_REQUEST)
session:同一个session创建一个实例。(WebApplicationContext.SCOPE_SESSION)
@Scope("prototype")
//@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean("person")
public Person person(){
return new Person("张三", 25);
}
@Lazy
懒加载:
1单实例bean:默认在容器启动的时候创建对象;
2非单实例bean:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化;
@Lazy
@Bean("person")
public Person person(){
return new Person("张三", 25);
}
@Conditional
按照一定的条件进行判断,满足条件给容器中注册bean。
可以指定多个Condition条件判断。
//判断是否linux系统
public class LinuxCondition implements Condition {
/**
* ConditionContext:判断条件能使用的上下文(环境)
* AnnotatedTypeMetadata:注释信息
*/
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//获取当前环境信息
Environment environment = context.getEnvironment();
//获取系统name
String property = environment.getProperty("os.name");
if(property.contains("linux")){
return true;
}
return false;
}
}
//判断是否windows系统
public class WindowsCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
if(property.contains("Windows")){
return true;
}
return false;
}
}
@Conditional(LinuxCondition.class)
@Bean("linus")
public Person person02(){
return new Person("linus", 48);
}
@Conditional(WindowsCondition.class)
@Bean("windows")
public Person person01(){
return new Person("windows",62);
}
@Test
public void test03(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
//在windows下获取的Person是id为"windows"的bean
//在windows下获取的Person是id为"linus"的bean
applicationContext.getBean(Person.class);
}
@Import
导入组件,id默认是组件的全类名。
@Configuration
@Import({Person.class,Red.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {
}
bean生命周期
bean创建--->初始化--->销毁的过程
spring容器中的流程:
BeanPostProcessor.postProcessBeforeInitialization===》初始化===》BeanPostProcessor.postProcessAfterInitialization===》销毁(单实例:容器关闭的时候; 多实例:容器不会调用销毁方法;)
spring源码调用:
//给bean进行属性赋值
populateBean(beanName, mbd, instanceWrapper);
initializeBean{
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
//执行自定义初始化
invokeInitMethods(beanName, wrappedBean, mbd);
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
方式一:
通过@Bean指定init-method(初始化方法)和destroy-method(销毁方法);
@Bean(initMethod="init",destroyMethod="detory")
public Car car(){
return new Car();
}
方式二:
通过InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑)
@Component
public class Car implements InitializingBean,Disposable{
public Car(){
}
//销毁
public void dispose() {
}
//初始化
public void afterPropertiesSet() throws Exception {
}
}
方式三:
使用JSR250的@PostConstruct(初始化)和@PreDestroy(销毁)
public class Car {
public Car() {
}
@PostConstruct
public void init() {
}
@PreDestroy
public void detory() {
}
}
@PropertySource
读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部的配置文件以后使用${}取出配置文件的值。
@PropertySource(value={"classpath:/person.properties"})
@Configuration
public class MainConfigOfPropertyValues {
@Bean
public Person person(){
return new Person();
}
}
public class Person{
@Value("张三")
private String name;
@Value("#{20-2}")
private Integer age;
@Value("${person.nickName}")
private String nickName;
}
ConfigurableEnvironment environment = applicationContext.getEnvironment();
String property = environment.getProperty("person.nickName");
@Value
1、基本数值
2、可以写SpEL; #{}
3、可以写${};取出配置文件【properties】中的值(在运行环境变量里面的值)
@Autowired
自动装配,Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值;
注入规则:
- 、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);
- 、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找 applicationContext.getBean("bookDao")
- 、@Autowired(required=false) 不是必须的。
- 、如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取
- 、AutowiredAnnotationBeanPostProcessor:解析完成自动装配功能;
@Qualifier
和@Autowired嵌套使用,指定需要装配的组件的id,例如:@Qualifier("bookDao")
@Service
public class BookService {
@Qualifier("bookDao")
@Autowired
private BookDao bookDao;
}
@Primary
Spring进行自动装配的时候,默认使用首选的bean。可以继续使用@Qualifier指定需要装配的bean的名字。
public class MainConifg {
@Bean("bookDao")
public BookDao bookDao(){
BookDao bookDao = new BookDao();
bookDao.setLable("2");
return bookDao;
}
@Primary
@Bean("bookDao2")
public BookDao bookDao(){
BookDao bookDao = new BookDao();
bookDao.setLable("2");
return bookDao;
}
}
在这里通过类型获取BookDao,默认装配bookDao2。
@Resource
java规范JSR250的注解,按照组件名称进行装配的。不支持@Primary功能,也没有@Autowired的reqiured=false;
@Service
public class BookService {
@Resource("bookDao")
private BookDao bookDao;
}
@Inject
和Autowired的功能一样,但是没有required=false的功能;
@Service
public class BookService {
@Inject
private BookDao bookDao;
}
@Profile
Profile:Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能;
该注解指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件。
规则:
1)、加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境。
2)、写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效。
3)、没有标注环境标识的bean在,任何环境下都是加载的;
@Profile("prod")
@Bean("prodDataSource")
public DataSource dataSourceProd() throws Exception{
//.....
return dataSource;
}
public void test01(){
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext();
//1、创建一个applicationContext
//2、设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("test");
//3、注册主配置类
applicationContext.register(MainConfig.class);
//4、启动刷新容器
applicationContext.refresh();
String[] namesForType = applicationContext.getBeanNamesForType(DataSource.class);
for (String string : namesForType) {
System.out.println(string);
}
applicationContext.close();
}
@EnableAsync
开启多线程支持
@ComponentScan("com.spring.async")
@EnableAsync
@Configuration
public class AsyncConfig {
}
@Service
public class UserService {
// 这里进行标注为异步任务,在执行此方法的时候,会单独开启线程来执行
@Async
public void f1() {
System.out.println(Thread.currentThread().getName());
}
}
AOP编程注解
@EnableAspectJAutoProxy
开启基于注解的aop模式。
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
}
然后通过AspectJAutoProxyRegistrar将AnnotationAwareAspectJAutoProxyCreator注册进入spring容器中。
@DeclareParents
动态添加方法。
切面相关注解
@Aspect:切面注解
@Pointcut:切点注解
@Before:前置通知
@After:后置通知
@AfterReturning:返回通知
@AfterThrowing:异常通知
@Around:环绕通知
public class MathCalculator {
public int div(int i,int j){
System.out.println("MathCalculator...div...");
return i/j;
}
}
@Aspect
public class LogAspects implements Ordered{
@DeclareParents(value="com.spring.aop.MathCalculator",defaultImpl=CalculatorImpl2.class)
private Calculator calculator;
@Before("bean(logAspects)&&this(calculator)")
public void logStart(Calculator calculator){
System.out.println(calculator.getString()+"0000+===");
}
public int getOrder() {
return 1;
}
@Pointcut("execution(public int com.spring.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.spring.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+"}");
}
}
public interface Calculator {
public int get(float a);
public String getString();
}
public class CalculatorImpl2 implements Calculator{
public int get(float a) {
return (int)Math.floor(a);
}
public String getString() {
return "实现类";
}
}
public void test01(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
mathCalculator.div(1, 1);
Calculator calculator=(Calculator) mathCalculator;
System.out.println(calculator.getString());
applicationContext.close();
}
事务注解
@EnableTransactionManagement
开启基于注解的事务管理功能。
@Transactional
表示当前方法是一个事务方法,当前方法的执行在一个事务中。
@EnableTransactionManagement
@ComponentScan("com.spring.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/testu");
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());
}
}
@Service
public class UserService {
@Autowired
private UserDao userDao;
@Transactional
public void insertUser(){
userDao.insert();
}
}
public class Test {
@Test
public void test01(){
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(TxConfig.class);
UserService userService = applicationContext.getBean(UserService.class);
userService.insertUser();
applicationContext.close();
}
}
事件驱动
@EventListener
事件与监听,可以与@Async结合使用,异步处理事件。
@Service
public class UserService {
@EventListener(classes = { ApplicationEvent.class })
public void listen(ApplicationEvent event) {
System.out.println("UserService。。监听到的事件:" + event);
}
}
或者通过接口实现方式的注入组件
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
//当容器中发布此事件以后,方法触发
public void onApplicationEvent(ApplicationEvent event) {
// TODO Auto-generated method stub
System.out.println("收到事件:"+event);
}
}