一、注入组件方式一:使用@Configuration和@Bean
1.1、对照组:通过原始xml方式给容器注入组件
、
bean:Person
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<bean id= "person" class="com.atguigu.bean.Person">
<property name="age" value="18"></property>
<property name="name" value="zhangsan"></property>
</bean>
</beans>
测试类MainTest.java
public class MainTest {
public static void main(String[] args) {
//使用ClassPathXmlApplicationContext根据名称加载解析类路径下的beans.xml文件,返回bean容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
//从容器中,根据名称获取bean实例对象
Person bean =(Person) applicationContext.getBean("person");
System.out.println(bean);
}
}
结果
1.2、使用@Configuration和@Bean注解
配置类MainConfig.java
//创建配置,这个配置类等同于beans.xml
@Configuration //告诉Spring这是一个配置类
public class MainConfig {
//给容器添加一个bean,类型为返回值的类型,id默认是用方法名作为id
@Bean("person")//指定id,此时方法名不再作为id
public Person person01() {
return new Person("ermao",20);
}
}
测试类MainTest.java
public class MainTest {
public static void main(String[] args) {
//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
//从容器中,通过类型获取bean
Person bean =(Person) applicationContext.getBean(Person.class);
System.out.println(bean);
//查看Person类型的组件在容器中的名字是什么
String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
for (String name : namesForType) {
System.out.println(name);
}
}
}
1.3、@ComponentScan自动扫描组件和配置扫描规则
1.3.1、对照组:通过原始xml结合<context:component-scan>
方式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 包扫描、只要标注了@Controller、@Service、@Repository,@Component都会被扫描 -->
<context:component-scan base-package="com.atguigu"></context:component-scan>
<bean id= "person" class="com.atguigu.bean.Person">
<property name="age" value="18"></property>
<property name="name" value="zhangsan"></property>
</bean>
</beans>
1.3.2、使用 @ComponentScan注解方式
MainConfig.java
//创建配置,这个配置类等同于beans.xml
@Configuration //告诉Spring这是一个配置类
@ComponentScan(value = "com.atguigu")//配置包扫描
public class MainConfig {
//给容器添加一个bean,类型为返回值的类型,id默认是用方法名作为id
@Bean("person")//指定id
public Person person01() {
return new Person("ermao",20);
}
}
测试
public class IOCTest {
@Test
public void test01() {
//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
//获取所有的bean,包括自定义和系统的所有bean
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
}
}
结果
1.3.3、通过对@ComponentScan注解设置参数配置扫描规则
1)、excludeFilters排除指定的,其他都扫描
//创建配置,这个配置类等同于beans.xml
@Configuration //告诉Spring这是一个配置类
@ComponentScan(value = "com.atguigu",excludeFilters = {
@Filter(type = FilterType.ANNOTATION,classes = {Controller.class,Service.class})
})//配置包扫描
public class MainConfig {
//给容器添加一个bean,类型为返回值的类型,id默认是用方法名作为id
@Bean("person")//指定id
public Person person01() {
return new Person("ermao",20);
}
}
2)、includeFilters只扫描指定的组件,加到容器中
//创建配置,这个配置类等同于beans.xml
@Configuration //告诉Spring这是一个配置类
@ComponentScan(value = "com.atguigu",includeFilters = {
@Filter(type = FilterType.ANNOTATION,classes = {Controller.class,Service.class})
},useDefaultFilters = false)//配置包扫描
public class MainConfig {
//给容器添加一个bean,类型为返回值的类型,id默认是用方法名作为id
@Bean("person")//指定id
public Person person01() {
return new Person("ermao",20);
}
}
3)、自定义Filter指定配置规则
自定义配置规则类和定义配置规则
MyTypeFilter.java
public class MyTypeFilter implements TypeFilter {
// metadataReader:读取到的当前正在扫描的类的信息.
// metadataReaderFactory :可以获取到其他任何类信息的
@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;
}
}
使用自定义的配置规则
MainConfig.java
//创建配置,这个配置类等同于beans.xml
@Configuration //告诉Spring这是一个配置类
@ComponentScan(value = "com.atguigu",includeFilters = {
//根据注解配置
// @Filter(type = FilterType.ANNOTATION,classes = {Controller.class,Service.class}),
//根据类型配置
// @Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {BookService.class}),
//自定义规则
@Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
},useDefaultFilters = false)//配置包扫描
public class MainConfig {
//给容器添加一个bean,类型为返回值的类型,id默认是用方法名作为id
@Bean("person")//指定id
public Person person01() {
return new Person("ermao",20,"二毛");
}
}
测试
@Test
public void test01() {
//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
//获取所有的bean
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
//关闭容器
applicationContext.close();
}
二、注入组件方式二:使用@Import快速注入
2.1、直接快速导入
快速导入组件
测试
@Test
public void test01() {
//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
//获取bean
String[] namesForType = applicationContext.getBeanDefinitionNames();
for (String name : namesForType) {
System.out.println(name);
}
//关闭容器
applicationContext.close();
}
结果
2.2、通过ImportSelector条件快速导入
将需要快速导入的组件放到一个ImportSelector类中,封装成数组返回
封装
MyImportSelector.java
//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {
//返回值,就是到导入到容器中的组件全类名
//AnnotationMetadata:当前标注@Import注解的类的所有注解信息
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//importingClassMetadata
//方法不要返回null值
return new String[]{"com.atguigu.bean.Blue","com.atguigu.bean.Yellow"};
}
}
注册
测试
@Tescst
public void test01() {
//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
//获取bean
String[] namesForType = applicationContext.getBeanDefinitionNames();
for (String name : namesForType) {
System.out.println(name);
}
//关闭容器
applicationContext.close();
}
2.3、通过ImportBeanDefinitionRegistrar:手动注册bean到容器中
MyImportBeanDefinitionRegistrar.java
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);
}
}
}
三、注入组件方式三:使用FactoryBean注入
创建一个Spring定义的FactoryBean
ColorFactoryBean.java
public class ColorFactoryBean implements FactoryBean<Color> {
//返回一个Color对象,这个对象会添加到容器中
@Override
public Color getObject() throws Exception {
System.out.println("ColorFactoryBean...getObject...");
return new Color();
}
@Override
public Class<?> getObjectType() {
return Color.class;
}
//是单例?
//true:这个bean是单实例,在容器中保存一份
//false:多实例,每次获取都会创建一个新的bean;
@Override
public boolean isSingleton() {
return false;
}
}
注册
MainConfig.java
测试
@Test
public void test01() {
//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
//工厂Bean获取的是调用getObject创建的对象
Object bean2 = applicationContext.getBean("colorFactoryBean");
Object bean3 = applicationContext.getBean("colorFactoryBean");
System.out.println("bean的类型:"+bean2.getClass());
System.out.println(bean2 == bean3);
Object bean4 = applicationContext.getBean("&colorFactoryBean");
System.out.println(bean4.getClass());
//关闭容器
applicationContext.close();
}
结果
四、@Scope设置组件作用域
4.1、对照组:相对于xml文件的scope属性
4.2、使用@Scope注解方式
设置
MainConfig.java
//创建配置,这个配置类等同于beans.xml
@Configuration //告诉Spring这是一个配置类
/*
* 默认是单实例
*
* prototype:多实例的:多实例的: ioc容器启动并不会去调用方法创建对象放在容器中。
每次获取的时候才会调用方法创建对象;
* singleton:单实例的(默认值): ioc容器启动会调用方法创建对象放到io.c容器中。
以后每次获取就是直接从容器中拿
* request:同一次请求创建一个实例
* session:同一个session创建一个实例
*/
@Scope("singleton")
public class MainConfig {
//给容器添加一个bean,类型为返回值的类型,id默认是用方法名作为id
@Bean("person")//指定id
public Person person01() {
return new Person("ermao",20,"二毛");
}
}
测试
@Test
public void test01() {
//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
//如果是单实例:初始化ioc容器启动会调用方法创建对象放到io.c容器中。以后每次获取就是直接从容器中拿
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
//通过类型获取bean
Person bean1 =(Person) applicationContext.getBean("person");//多实例,每次获取的时候才会调用方法创建对象
Person bean2 =(Person) applicationContext.getBean("person");
System.out.println(bean1 == bean2);
//关闭容器
applicationContext.close();
}
结果
五、@Lazy组件懒加载
配置
MainConfig.java
//创建配置,这个配置类等同于beans.xml
@Configuration //告诉Spring这是一个配置类
/*
* 默认是单实例
* singleton:单实例的(默认值): ioc容器启动会调用方法创建对象放到io.c容器中。
以后每次获取就是直接从容器中拿
*/
@Scope("singleton")
/*
* 懒加载:
单实例bean:默认在容器启动的时候创建对象;
懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化;
*/
@Lazy
public class MainConfig {
//给容器添加一个bean,类型为返回值的类型,id默认是用方法名作为id
@Bean("person")//指定id
public Person person01() {
System.out.println("给容器添加组件...");
return new Person("ermao",20,"二毛");
}
}
测试
@Test
public void test01() {
//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
//1、如果是单实例:使用懒加载后,初始化ioc容器不会自动调用创建的对象
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
//通过类型获取bean
//2、直到使用的时候才会调用创建的对象
Person bean1 =(Person) applicationContext.getBean("person");
Person bean2 =(Person) applicationContext.getBean("person");
System.out.println(bean1 == bean2);
//关闭容器
applicationContext.close();
}
结果
六、@Conditional根据条件装配组件
条件装配:满足Conditional指定的条件,则进行组件注入
自定义条件
WindowsCondition.java
//判断是否windows系统
public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//获取操作系统的名称
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
//如果操作系统是Windows,则返回true
if(property.contains("Windows")){
return true;
}
return false;
}
}
LinuxCondition.java
public class LinuxCondition implements Condition {
/**
* ConditionContext:判断条件能使用的上下文(环境)
* AnnotatedTypeMetadata:注释信息
*/
@Override
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();
String property = environment.getProperty("os.name");
//如果操作系统是linux,则返回true
if(property.contains("linux")){
return true;
}
return false;
}
}
向容器注册bean
MainConfig.java
@Configuration
public class MainConfig {
/**
* @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean
*
* 如果系统是windows,给容器中注册("bill")
* 如果是linux系统,给容器中注册("linus")
*/
@Conditional(WindowsCondition.class)
@Bean("bill")
public Person person01(){
return new Person("Bill Gates",62,"比尔盖茨");
}
@Conditional(LinuxCondition.class)
@Bean("linus")
public Person person02(){
return new Person("linus", 48,"林牛斯");
}
}
测试
@Test
public void test01() {
//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
//根据类型获取所有的bean的名称
String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
for (String name : namesForType) {
System.out.println(name);
}
//获取当前操作系统名称的第二种方式
ConfigurableEnvironment environment = applicationContext.getEnvironment();
//动态获取环境变量的值;Windows 10
String property = environment.getProperty("os.name");
System.out.println(property);
Map<String, Person> persons = applicationContext.getBeansOfType(Person.class);
System.out.println(persons);
//关闭容器
applicationContext.close();
}
结果
@Conditional注解也可以放在类上,即满足条件,类中的所有bean才会注册
七、bean生命周期:通过@Bean指定init-method和destroy-method;
7.1、基本概念
1、bean的生命周期:bean创建—初始化----销毁的过程
2、容器管理bean的生命周期:我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法
3、指定初始化和销毁方法
a、使用原始xml方式是这样指定bean的初始化和销毁方法的
b、通过@Bean指定init-method和destroy-method;
BeanPostProcessor.postProcessBeforeInitialization
初始化:
对象创建完成,并赋值好,调用初始化方法。。。
BeanPostProcessor.postProcessAfterInitialization
销毁:
单实例:容器关闭的时候
多实例:容器不会管理这个bean;容器不会调用销毁方法;
4、构造(对象创建)
单实例:在容器启动的时候创建对象
多实例:在每次获取的时候创建对象
7.2、指定初始化和销毁方式一
结果
7.3、指定初始化和销毁方式二
通过让Bean实现InitializingBean(定义初始化逻辑),
通过让Bean实现DisposableBean(定义销毁逻辑);
将bean扫描到容器中
测试
结果
7.4、指定初始化和销毁方式三
可以使用JSR250;
@PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法
@PreDestroy:在容器销毁bean之前通知我们进行清理工作
7.5、指定初始化和销毁方式四
BeanPostProcessor【interface】:bean的后置处理器;
在bean初始化前后进行一些处理工作;
postProcessBeforeInitialization:在初始化之前工作
postProcessAfterInitialization:在初始化之后工作
八、属性赋值
8.1、@Value直接赋值
测试
public class IOCTest {
@Test
public void test01() {
//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
//获取所有的bean
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
//通过类型获取bean
Person bean =(Person) applicationContext.getBean("person");
System.out.println(bean);
//关闭容器
applicationContext.close();
}
}
结果
8.2、@Value使用properties文件的值赋值
创建properties文件
加载properties文件
使用properties文件
测试
@Test
public void test01() {
//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
//获取所有的bean
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
//通过类型获取bean
Person bean =(Person) applicationContext.getBean("person");
System.out.println(bean);
//关闭容器
applicationContext.close();
}
将加载到容器后也可以在任意地方直接获取使用
@Test
public void test01() {
//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
//获取所有的bean
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
//通过类型获取bean
Person bean =(Person) applicationContext.getBean("person");
System.out.println(bean);
//从环境变量中获取properties文件的值
ConfigurableEnvironment environment = applicationContext.getEnvironment();
String property = environment.getProperty("person.nickName");
System.out.println(property);
//关闭容器
applicationContext.close();
}
九、自动装配
自动装配:Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值;
9.1、@Autowired(Spring规范的注解)
1)、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值
2)、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
applicationContext.getBean(“bookDao”)
3)、@Qualifier(“bookDao”):使用@Qualifier指定需要装配的组件的id,而不是使用属性名
4)、自动装配默认一定要将属性赋值好,没有就会报错;
可以使用@Autowired(required=false);
5)、@Primary:让Spring进行自动装配的时候,默认使用首选的bean;
也可以继续使用@Qualifier指定需要装配的bean的名字
9.2、Java规范的注解
9.2.1、@Resource(JSR250规范)
@Resource:
可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;
没有能支持@Primary功能没有支持@Autowired(reqiured=false);
在上述9.1的基础上知识修改service
9.2.2、@Inject(JSR330规范)
@Inject:
需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;
在上述9.1的基础上知识修改service
9.3、@Autowired的其他用法
9.3.1、@Autowired:标注在方法上
@Autowired
标注在方法,Spring容器创建当前对象,就会调用方法,完成赋值;
方法使用的参数,自定义类型的值从ioc容器中获取
9.3.2、@Autowired:标注在构造器上
如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取
9.3.3、@Autowired:标注在放在参数位置
9.3.4、@bean创建对象的使用@Autowired可省略不写
9.4、自定义组件使用Spring容器底层的一些组件
自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx);
自定义组件实现xxxAware;在创建对象的时候,会调用接口规定的方法注入相关组件;Aware;
把Spring底层一些组件注入到自定义的Bean中;
xxxAware:功能使用xxxProcessor;
ApplicationContextAware==》ApplicationContextAwareProcessor;
这里演示继承三个Aware
9.5、@Profile环境搭建
Profile:
Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能;
开发环境、测试环境、生产环境;
数据源:(/A)(/B)(/C);
@Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件
MainConfigOfProfile.java
//1、没有标注环境标识的bean在,任何环境下都是加载的;
//@Profile("test")//2、写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
@PropertySource("classpath:/dbconfig.properties")
@Configuration
public class MainConfigOfProfile implements EmbeddedValueResolverAware{
@Value("${db.user}")
private String user;
private StringValueResolver valueResolver;
private String driverClass;
@Profile("test")//3、配置在组件上,只有是指定的环境的时候,组件才能开始生效
@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}");
}
}
9.5.1、使用命令行动态参数: 在虚拟机参数位置加载 -Dspring.profiles.active=test
9.5.2、代码的方式激活某种环境
十、AOP
AOP:【动态代理】
指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式;
1、导入aop模块;Spring AOP:(spring-aspects)
2、定义一个业务逻辑类(MathCalculator);在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)
3、定义一个日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行;
通知方法:
前置通知(@Before):logStart:在目标方法(div)运行之前运行
后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)
返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行
异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行
环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
4、给切面类的目标方法标注何时何地运行(通知注解);
5、将切面类和业务逻辑类(目标方法所在类)都加入到容器中;
6、必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
7、给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】
在Spring中很多的 @EnableXXX;
三步:
1)、将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个是切面类(@Aspect)
2)、在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)
3)、开启基于注解的aop模式;@EnableAspectJAutoProxy
10.1、导入aop模块;
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
10.2、定义一个业务逻辑类(MathCalculator)
10.3、定义一个日志切面类(LogAspects)
10.4、给切面类的目标方法标注何时何地运行(通知注解)
@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+"}");
}
}
10.5、将切面类和业务逻辑类(目标方法所在类)都加入到容器中;
十一、声明式事务
TxConfig.java
@EnableTransactionManagement//第一步:开启事务管理功能
@ComponentScan("com.atguigu.tx")
@Configuration
public class TxConfig {
//数据源
@Bean
public DataSource dataSource() throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("756865");
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());
}
}
十二、注解版的Web:
12.1、基础知识
servlet3.0属于JSR315规范,支持的Tomcat版本是Tomcat7及以上
创建一个动态web工程,不使用web.xml
12.2、基础使用@WebServlet
12.3、ServletContainerInitializer及servlet容器的初始化的实现类
1、Servlet容器启动会扫描,当前应用里面每一个jar包的ServletContainerInitializer的实现
2、提供ServletContainerInitializer的实现类;必须绑定在,META-INF/services/javax.servlet.ServletContainerInitializer
文件的内容就是ServletContainerInitializer实现类的全类名;
总结:容器在启动应用的时候,会扫描当前应用每一个jar包里面
META-INF/services/javax.servlet.ServletContainerInitializer
指定的实现类,启动并运行这个实现类的方法;传入感兴趣的类型;
index.jsp和HelloServlet.java如12.2所示
12.4、使用ServletContext注册Web组件(Servlet、Filter、Listener)
12.5、springmvc注解版(没有web.xml)
12.5.1、基础用法
12.5.2、定制MVC
定制SpringMVC;
1)、@EnableWebMvc:开启SpringMVC定制配置功能;
<mvc:annotation-driven/>;
2)、配置组件(视图解析器、视图映射、静态资源映射、拦截器。。。)
extends WebMvcConfigurerAdapter