Spring学习笔记-06. 如何与Spring集成

全局组件初始化

对于组件的全局的初始化,可以使用前面所说的ImportBeanDefinitionRegistrar这个方法来指定初始化方法,以开源的队列QMQ的源码为例:

@EnableQmq实现方式

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(QmqConsumerRegister.class)
public @interface EnableQmq {

    String appCode();

    String metaServer();
}

其中QmqConsumerRegister实现代码如下

 @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
      ...
    }

Spring在扫描包的时候,会自动的运行registerBeanDefinitions中的方法,实现组件初始化。

单实体使用

利用bean的生命周期可以优雅的实现,其中 @PostConstruct和@PreDestroy写法更容易,也比较好控制,缺点就是需要找到的对应的入口,对于源码阅读不是很友好。

阅读更多

Spring学习笔记-05. Spring事务的使用

配置HikariDataSource测试环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Configuration
public class RzConfig {
@Bean
public DataSource dataSource() {
//此处也可以写到配置文件中
final HikariConfig cpConfig = new HikariConfig();
cpConfig.setDriverClassName("com.mysql.cj.jdbc.Driver");
cpConfig.setJdbcUrl("jdbc:mysql://localhost:3306/rzframe?characterEncoding=utf8&useSSL=true&autoReconnect=true&failOverReadOnly=false&serverTimezone=UTC");
cpConfig.setUsername("root");
cpConfig.setPassword("abc12345");
cpConfig.setMaximumPoolSize(10);
HikariDataSource hikariDataSource = new HikariDataSource(cpConfig);
return hikariDataSource;
}
@Bean
public JdbcTemplate jdbcTemplate(){
return new JdbcTemplate(dataSource());
}
}

编写事务代码和执行

  1. @Configuration增加@EnableTransactionManagement注解

  2. 注册PlatformTransactionManager

1
2
3
4
5
@Bean
public PlatformTransactionManager platformTransactionManager(){
return new DataSourceTransactionManager(dataSource());
}

  1. 写一个Service主动抛出异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

@Service
public class MenuService {
@Autowired
JdbcTemplate jdbcTemplate;

@Transactional
public void insertMenu() throws Exception {
String sql = "insert into `rz_menu` (`menu_name`, `menu_src`, `menu_icon`, `menu_status`, `parentmenu_id`, `create_time`, `dataChange_lastTime`) values('test','/','fa-desktop','0','0',now(),now());";
jdbcTemplate.execute(sql);
int i = 1 / 0;

}
}

执行Service 程序运行报错,数据也无法正常的插入。

阅读更多

Spring学习笔记-04.Spring AOP的使用

AOP的使用


所谓AOP的思想是现在程序设计中常用的一种设计思想,主要是为了能够更好的监控程序的运行的情况。 在Spring中AOP的思想展现的淋漓尽致。

实现一个简单的AOP。

1
2
3
4
5
6
7
8
@Component
public class OrderBiz {

public void doSomething(int x, int y) {
System.out.println(x + y);
}
}

增加一个AOP的类:

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
@Aspect
public class LogAspector {

//此处是一个入口,定义为OrderBiz的所有方法
@Pointcut("execution(public void learnJava.spring.sprz05.OrderBiz.*(..))")
public void pointCut(){}

@Before("pointCut()")
public void logStart(JoinPoint joinPoint) {
System.out.println(joinPoint);
RzLogger.info("方法开始执行....");
}

@After("pointCut()")
public void logEnd() {
RzLogger.info("方法执行完成....");
}

@AfterReturning("pointCut()")
public void logReturn() {
RzLogger.info("方法执行结束返回数据....");
}
@AfterThrowing(value = "pointCut()",throwing = "ex")
public void logException(Exception ex) {
RzLogger.info("方法执行异常....");
RzLogger.error(JsonUtils.serializeObject(ex));
}

@Around("pointCut()")
public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
RzLogger.info("Around开始");
Object proceed = joinPoint.proceed();
RzLogger.info("Around结束");
return proceed;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
@EnableAspectJAutoProxy //不可缺少
public class ConfigMain {

@Bean
public OrderBiz getOrderBiz(){
return new OrderBiz();
}

@Bean
public LogAspector getLogAspector(){
return new LogAspector();
}
}


主方法的调用

1
2
3
4
5
6
7
public static void main(String[] args) {

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigMain.class);
OrderBiz bean = applicationContext.getBean(OrderBiz.class);
bean.doSomething(1, 3);

}

代码执行结果:

阅读更多

Spring学习笔记-03.Bean的创建方式

在Spring容器中,实例对象都会有三个过程,创建,初始化和消亡。

创建 Bean 的方式


@Bean 注解指定方法

1
2
3
4
@Bean(initMethod = "init",destroyMethod = "destroy")
public Dog getDog(){
return new Dog();
}

InitializingBean和DisposableBean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Cat implements InitializingBean, DisposableBean {
public Cat(){
RzLogger.info("cat create");
}
@Override
public void destroy() throws Exception {
RzLogger.info("cat destroy");
}

/**
* 在容器创建的时候调用
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
RzLogger.info("cat afterPropertiesSet");
}
}

@PostConstruct和 @PreDestroy

阅读更多

Spring学习笔记-02.Spring 实体的注入

IOC的使用

@Configuration是入口

在Spring中,在一个类的上面增加@Configuration注解,这个就表示当前为配置类,可以代替xml形式的配置形式。在类中可以定义各种bean的定义,这些定义会被AnnotationConfigApplicationContext容器扫描。

1
2
3
4
5
@Configuration
public class RzConfig
{

}

注入的@Configuration对象可以通过configApplicationContext.getBeanDefinitionNames()方法获得对应的集合

1
2
3
4
5
AnnotationConfigApplicationContext configApplicationContext=new AnnotationConfigApplicationContext(RzConfig.class);
String[] beanDefinitionNames = configApplicationContext.getBeanDefinitionNames();
for (int i = 0; i < beanDefinitionNames.length; i++) {
RzLogger.info("获得注入的类:"+beanDefinitionNames[i]);
}
1
2
3
4
5
6
23:24:18,150  INFO [main] (RzLogger.java:12) - 获得注入的类:org.springframework.context.annotation.internalConfigurationAnnotationProcessor
23:24:18,154 INFO [main] (RzLogger.java:12) - 获得注入的类:org.springframework.context.annotation.internalAutowiredAnnotationProcessor
23:24:18,154 INFO [main] (RzLogger.java:12) - 获得注入的类:org.springframework.context.annotation.internalCommonAnnotationProcessor
23:24:18,154 INFO [main] (RzLogger.java:12) - 获得注入的类:org.springframework.context.event.internalEventListenerProcessor
23:24:18,154 INFO [main] (RzLogger.java:12) - 获得注入的类:org.springframework.context.event.internalEventListenerFactory
23:24:18,154 INFO [main] (RzLogger.java:12) - 获得注入的类:rzConfig

@Bean的使用

@Bean代表一个类实体,可以定义一个Id,类似代码:

阅读更多