spring注解开发(一)

本文详细介绍了Spring框架的多种ApplicationContext创建方式,包括通过XML配置、注解配置及混合配置,探讨了组件扫描、生命周期管理、依赖注入、条件化组件注册、异步支持、AOP、事务管理、事件监听等关键特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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容器中中各个组件的依赖关系赋值;

注入规则:

  1. 、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);
  2. 、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找 applicationContext.getBean("bookDao")
  3. 、@Autowired(required=false) 不是必须的。
  4. 、如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取
  5. 、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);

}



}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流光影下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值