`
》》Spring初级注解
1.配置文件Bean标签对应注解
1.1配置包扫描
<!--包扫描 让Spring去扫描本包及其子包中的注解 包括@Component等其他的注解 -->
<context:component-scan base-package="包名">
1.2@Component注解
1.2.1作用及基本使用
作用:替换Spring配置文件中的<bean id= class= >标签
用法:
@Component
public class User{
}
id的值默认是类名小写
class的值会通过反射获取全类名
代码示例
@Component
public class User {
private Integer id;
private String name;
private String password;
}
测试
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//默认的id就是类名首字母小写
User user = (User) applicationContext.getBean("user");
//通过测试 获取到了工厂创建的对象
System.out.println(user);
}
1.2.2注解源码
@Target(ElementType.TYPE) //表示 此注解只能标注在类 接口 枚举类上
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
String value() default ""; //这个value属性就是可以为这个对象自定义一个id属性
}
@Component("自定义id")
public class User {
private Integer id;
private String name;
private String password;
}
1.2.3使用配置文件覆盖注解配置内容
如果注解和配置文件都使用了,那么配置文件会覆盖注解,前提是配置文件中的配置的id属性与注解的id属性相同
如果id不同,那么Spring就会创建不同的对象
1.2.4@Component衍生注解
@Repository ----用在xxxDAO实现类上 (不使用,DAO接口的实现类都是Mybatis做的)
@Service ----用在xxxServieImpl上
@Controller ----用在xxxController上
本质上这几个衍生注解就是@Component
目的:更加准确的表达一个类的作用 使用跟@Component一样
1.3@Scope注解
控制对象的创建次数,类似于bean标签中的scope属性
<bean id="" class="" scope="singleton/prototype"></bean>
使用方式
@Component
@Scope(value = "prototype/singleton") //默认是singleton
public class User {
private Integer id;
private String name;
private String password;
}
1.4@Lazy注解
控制对象的加载时机,默认scope为singleton的bean是Spring工厂创建的时候就被创建
,可以设置@lazy注解设置懒加载。
@Component
//true代表开启懒加载,false表示关闭懒加载,只对singleton的Bean有效
@Lazy(value = true/false)
public class User {
private Integer id;
private String name;
private String password;
}
1.5@Component注解总结
- 1、只能标注在类 注解 枚举类上
- 2、作用等同于
Spring配置文件中的bean标签
- 3、衍生注解 @Repository @Service @Controller
- 4、没有显示赋值
默认bean的id类名小写
2.关于Bean的生命周期的注解
2.1bean生命周期回顾概述
进行Bean的初始化要实现Spring规定的InitializingBean接口实现其规定方法,或者自定义方法在bean标签中配置init-method属性此方法
使用注解开发,只需要在这个类的自定义的初始化方法中使用@PostConstruct注解即可
进行Bean的销毁要实现Spring规定的DisposableBean接口并实现其方法,或者自定义方法在bean标签中配置destoty-method属性指定此方法 (注意:销毁只针对于singleton且只在工厂关闭时有效)
使用注解开发,只需要在这个类的自定义销毁方法上使用@PreDestory注解即可
2.2@PostConstruct初始化
@Component
public class User {
private Integer id;
private String name;
private String password;
@PostConstruct
public void myInit(){
}
}
2.3@PreDestory销毁
@Component
public class User {
private Integer id;
private String name;
private String password;
@PreDestroy
public void myDestory(){
}
}
3.关于属性注入相关注解
3.1@Autowired注解(自定义类型)
3.1.1回顾注入
注入本质上就是调用set方法为其赋值
配置文件注入编码
public class UserDaoImpl implements UserDao {
@Override
public void query() {
System.out.println("调用了query方法");
}
}
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void select() {
}
}
<?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.xsd">
<bean id="userDao" class="com.shwsh.dao.UserDaoImpl"></bean>
<bean id="userService" class="com.shwsh.service.UserServiceImpl">
<!--这里调用的是UserServiceImpl类的set方法,使用userDao对象为其赋值-->
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
3.1.2使用@Autowired注解
注意:@Autowired注解是根据类中的属性类型
来进行注入的,即你标注了@Autowired注解,然后Spring就会根据你的set方法的需要注入的类型(可以是接口的实现类或者是其子类
)寻找工厂中的对应类型的对象给你注入
@Service
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
//标注在set方法中,寻找工厂中对应的UserDao接口的实现类对象然后调用这个set方法实现注入
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void select() {
}
}
@Repository
public class UserDaoImpl implements UserDao {
@Override
public void query() {
System.out.println("调用了query方法");
}
}
3.1.3使用@Qualifier注解配合 @Autowired实现基于id属性注入
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void query() {
System.out.println("调用了query方法");
}
}
@Service("userService")
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
@Autowired
//这里的属性一定要跟对应bean的id属性一致 即指定id注入 也要配合着@Autowired属性一起使用
@Qualifier("userDao")
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void select() {
userDao.query();
}
}
3.1.4@Autowired注解的另一个使用位置-直接标注在属性上
标注在属性上的话,Spring通过反射直接对成员变量进行赋值
@Service("userService")
public class UserServiceImpl implements UserService {
//直接标注在属性上,Spring通过反射获取这个属性直接为其赋值,不调用set方法,
//@Qualifier()也可以直接标在属性上,作用跟标在方法上相同,都是根据id属性获取bean
@Autowired
@Qualifier("userDao")
private UserDao userDao;
@Override
public void select() {
userDao.query();
}
}
3.1.5@Resource注解与@Inject注解
@Resource非Spring提供的注解,是JavaEE规范提供的注解,它能基于类型或id属性进行注入
当为@Resource的value属性赋了值时(即指定了某一个bean的id属性),就是基于id属性进行注入,如果没有为其赋值,就是基于类型进行注入
@Inject是基于类型进行注入,常用与EJB3.0,要引入其依赖
javax.inject
3.1.6注入类型总结
1、可以标注在set方法
或者直接标注在属性上
2、如果标注在set方法上Spring会直接调用set方法为属性注入
3、如果直接标注在属性上,Spring会通过反射直接获取这个属性,然后为其注入
4、@Autowired是基于类型
进行注入的,可以结合@Qualifier("bean id")
基于id属性进行注入
5、@Resource当不指定value属性时是基于类型进行注入,指定了id值就基于id进行注入
3.2JDK类型注入
3.2.1@Value注解使用步骤
1、使用xx.properties以kv的形式
2、在Spring的配置文件中引入这个配置文件
使用<context:property-placeholder location=""/>
3、使用@Value注解直接标注在对应的属性上并使用${key}为其赋值,
3.2.2@Value总结
不能为静态属性赋值
不能为集合类型赋值
3.2.2@PropertySource注解
作用:替换上面在注入过程中第二步在Spring配置文件中引入外部的properties配置文件的标签
替换之后的开发步骤
1、使用xx.properties以kv的形式
2、应用@PropertySource(value="xx.properties路径"),标注在类上
3、使用@Value注解直接标注在对应的属性上并使用${key}为其赋值,
4.注解扫描详解
4.1扫描回顾
<context:component-scan base-package="com.xx"/>
默认会扫描 当前包及其子包
4.2排除策略
<context:component-scan base-package="com.baizhiedu">
<context:exclude-filter type="" expression=""/>
type:assignable:排除特定的类型 不进行扫描
annotation:排除特定的注解 不进行扫描
aspectj:切入点表达式 (常用)
包切入点: com.baizhiedu.bean..*
类切入点: *..User
regex:正则表达式
custom:自定义排除策略框架底层开发
</context:component-scan>
排除策略可以叠加使用
<context:component-scan base-package="com.baizhiedu">
<context:exclude-filter type="assignable" expression="com.baizhiedu.bean.User"/>
<context:exclude-filter type="aspectj" expression="com.baizhiedu.injection..*"/>
</context:component-scan>
4.3包含策略
<context:component-scan base-package="com.baizhiedu" use-default-filters="false">
<context:include-filter type="" expression=""/>
</context:component-scan>
1. use-default-filters="false"
作用:让Spring默认的注解扫描方式 失效。
2. <context:include-filter type="" expression=""/>
作用:指定扫描那些注解
type:assignable:排除特定的类型 不进行扫描
annotation:排除特定的注解 不进行扫描
aspectj:切入点表达式
包切入点: com.baizhiedu.bean..*
类切入点: *..User
regex:正则表达式
custom:自定义排除策略框架底层开发
包含的方式支持叠加
<context:component-scan base-package="com.baizhiedu" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
5.注解的其他细节
Spring注解和配置文件是可以互通的,即在配置文件中可以引用使用注解配置的bean,在类中也可以使用配置文件中配置的bean
什么情况下需要使用注解,什么情况下需要使用配置文件?
我们自定义的类可以使用注解,比如UserServiceImpl,UserCotroller等
非我们开发的类由第三方框架提供的类我们还必须使用配置文件的方式(到目前阶段),比如前面我们整合Mybatis,第三方jar包为我们提供的两个核心类,SqlSessionFactoryBean(创建Mybatis中的SqlSessionFactory)以及MapperScannerConfigure(为我们的Dao接口生成代理类对象),像这些类我们还得使用配置文件的方式
》》Spring高级注解(3.x及以上)
6.@Configurantion注解
6.1概述与基本使用
作用:完全替换了Spring的配置文件applicationContext.xml,即只要有一个类加入了@Configuration注解,那么这个类就相当于是一个Spring的applicationContext配置文件
也是@Component的衍生注解
注意:在使用Spring的配置文件时,我们的工厂是ClassPathXmlApplication,而我们使用@Configurantion注解时,想要获取工厂使用的是AnnotationConfigApplicationContext这个类
使用注解创建工厂
@Configuration
public class MyConfig {
}
获取工厂
@Test
public void test2(){
ApplicationContext context = new
AnnotationConfigApplicationContext(MyConfig.class);
//获取工厂,直接传入配置类对象,可以传入多个配置类
//第二种获取配置工厂方式,传入包名 Spring自动扫描这个包及其子包下的所有@Configuration的类
ApplicationContext context1 = new AnnotationConfigApplicationContext("com.shwsh");
}
}
6.2简单原理(Cglib代理)
配置类的原理是代理模式,使用的是Cglib代理,为配置类创建一个代理模式,为其@Bean方法增加额外功能,包括(对象的创建次数等。。。)
7.@Bean注解
7.1概述
必须@Configuration标注的类中进行使用,相当于applicationContext.xml中的一个个的bean标签
7.2.1简单对象&复杂对象的创建及细节
默认的方法名就是bean的id属性,方法的返回值就是bean的class属性 方法体内直接写创建对象过程即可
可以自定义bean的id,直接在bean标签的value属性中自定义id值--->@Bean("id")
可以使用@Scope("singleton/prototype")控制对象的创建次数默认是singleton
@Configuration
public class MyConfig {
----简单对象创建
//(默认情况)方法名user就是bean的id属性 返回值就是class属性
@Bean("u") //自定义id属性
public User user() {
return new User();
}
----复杂对象的创建
//方法名就是bean的id属性 返回值是class属性
@Bean
@Scope("prototype") //控制对象的创建次数
public Connection conn() {
Connection connection = null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("xxx", "xx", "xx");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return connection;
}
}
7.2.2基于@Bean注解的属性注入
7.2.2.1自定义类型的注入
两种方式
@Bean
public A a() {
return new A();
}
//第一种方式,直接将A声明在方法的参数中,然后调用set方法赋值
@Bean("b1")
public B b(A a) {
B b = new B();
b.setA(a);
return b;
}
//第二种方式,直接调用a方法为其注入
@Bean("b2")
public B b() {
B b = new B();
b.setA(a());
return b;
}
7.2.2.2JDK类型的注入
基于JDK类型的注入,直接在创建方法内部创建对象时直接赋值即可
@Bean
public User user() {
User user = new User();
user.setId(1);
user.setName("xdsa");
return user;
}
8.@ComponentScan注解
8.1概述
作用:替换原Spring配置文件中的<context:component-scan>标签,扫描指定的注解
使用:用在@Configuration标注的配置类中
8.2基本使用
@Configuration
//扫描指定包及其子包下的注解 (该创建对象创建对象,该注入的注入...)
@ComponentScan(basePackages = "com.shwsh")
public class MyConfig {
}
8.2扫描排除与包含
排除
<context:component-scan base-package="com.baizhiedu">
<context:exclude-filter type="assignable" expression="com.baizhiedu.bean.User"/>
</context:component-scan>
@ComponentScan(basePackages = "com.baizhiedu.scan",
excludeFilters = {@ComponentScan.Filter(type= FilterType.ANNOTATION,value={Service.class}),
@ComponentScan.Filter(type= FilterType.ASPECTJ,pattern = "*..User1")})
----对应
type = FilterType.ANNOTATION value
.ASSIGNABLE_TYPE value
.ASPECTJ pattern
.REGEX pattern
.CUSTOM value
包含
<context:component-scan base-package="com.baizhiedu" use-default-filters="false">
<context:include-filter type="" expression=""/>
</context:component-scan>
@ComponentScan(basePackages = "com.baizhiedu.scan",
//设置不使用默认的扫描策略 只扫描指定的
useDefaultFilters = false,
includeFilters = {@ComponentScan.Filter(type= FilterType.ANNOTATION,value={Service.class})})
---对应
type = FilterType.ANNOTATION value
.ASSIGNABLE_TYPE value
.ASPECTJ pattern
.REGEX pattern
.CUSTOM value
9.高级注解使用总结
Spring的applicationContext.xml配置文件,在SpringBoot的开发中完全被弃用,完全被注解代替,下面看一下配置问价的核心部分被替换成了什么注解
------------------------------------------------------------------------------
即看到一个被@Configuration标注的类,就把他当做是一个Spring的applicationContext.xml配置文件
applciationContext.xml ----> @Configuration
<bean id = "" class="" scope="" lazy-init=""> ----> @Bean + @Scope + @Lazy
<context:component-scan base-package="com.shwsh"> ----->@ComponentScan()
<context:property-placeholder location="" /> ----> @PropertySource()
${}赋值 ----@Value("${key}")
....
<--------------------------------------------------------------------------->
@Component及其衍生注解替换的也是配置文件中的Bean标签,由于@Component需要配置包扫描,所以要想这些注解起作用的话必须要配置包扫描,使用@ComponentScan()注解或者在配置文件中配置包扫描
<--------------------------------------------------------------------------->
@Autowired注解是在标注了@Component及其衍生注解中为属性进行注入的,根据类型注入,组合@Qualifier注解可以根据id属性注入
而
在@Configuration配置类的标注@Bean方法中想要为bean赋值,JDK类型直接调用set方法,自定义类型的注入直接调用对应bean的创建方法或者在方法的参数中声明,然后Spring根据类型自动注入
(参考7.2.2)
<--------------------------------------------------------------------------->
所以说,@Autowired(@Resource)跟@Component及其衍生注解一起使用(一定要有包扫描才起作用)
@Configuration+@Bean+@ComponentScan()+@PropertySource()+..一起使用
10.Spring工厂创建对象的多种配置方式及整合
10.1多种配置方式的应用场景及@Import
1、Spring的applicationContext.xml
在纯注解的开发过程中基本不使用
2、@Component+包扫描
用于自定义类型的配置,如UserService UserController
3、@Configuration+@Bean
用于第三方的框架提供给的类,
如 SqlSessionFactoryBean MapperSacnnerConfigure
4、@Configuration+@Import
向工厂中导入指定类型的Bean @Import(xxx.class)
我们基本不使用,Spring底层大量使用
10.2Spring多种创建对象方式的优先级
多种配置可以同时起作用(保证id不能相同),但是有优先级 优先级高的配置可以覆盖优先级低的配置
(覆盖的前提:id要一样)
优先级从低到高排列
@Component及其衍生注解< @Bean < 配置文件的bean标签
10.3多个配置之间的整合
10.3.1配置类整合Spring配置文件(@ImportResource)
只需在配置类上使用@ImportResource("配置文件位置")
代码示例
@Configuration
@ImportResource("Spring配置文件的位置") //将Spring的配置文件整合到此工厂中
public class MyConfig {
}
10.3.2配置类之间整合
第一种方式
一般都将所有的配置类都创建在一个包中,所以直接在创建工厂时进行包扫描即可
ApplicationContext c = new AnnotationApplicationContext("com.shwsh.config");
第二种方式
使用@Import注解,将其他的配置类导入进来
@Impot相当于Spring配置文件中的<import标签,将其他的配置文件整合进来,因为最后Spring只会创建一个工厂,
@Configuration
@ComponentScan(basePackages = "com.shwsh")
@Import(OtherConfig.class)
@Import(OtherConfig1.class)
...
public class MyConfig {
}
10.3.3配置类与@Component及其衍生注解的整合
在配置类上加入@ComponentScan注解,进行注解扫描
@ComponentScan("com.shwsh")
@Configuration
public class MyConfig{
@Bean
...
}
10.4整合之后的注入
在对所有的配置进行整合完毕后,想要注入,直接使用 @Autowired注解即可
或者是直接在创建工厂时指定多个配置类,这样在不整合配置类的前提下就可以使用@Autowired注入
@Configuration
@Import(MyConfig2.class)
public class MyConfig1{
//整合所有的配置之后,直接使用@Autowired即可
@Autowired
private B b;
@Bean
public A a(){
A a = new A();
a.setB(b);
retuen a;
}
}
@Configuration
public class MyConfig2{
@Bean
public B b(){
B b = new B();
return b;
}
}
10.5整合及注入总结
整合总结
- 配置类与配置文件整合,使用
@ImportResource(配置文件位置)
注解 - 配置类与@Component及其衍生注解整合,使用
@ComponentScan(指定包)
注解进行扫描 - 配置类之间的整合,使用
@Import(配置类.class)
注解
注入只需要在整合完成以后(或者创建工厂时指定包扫描配置类),只需要使用@Autowired注解注入即可
11.四维一体
不管我们配置的标签还是注解,最终都是使用底层对应的处理类来实现的,比如我们引入外部的properties配置文件,不管是在Spring配置文件中使用<context:property-placeholder location=“”/>还是使用注解@PropertySource引入,底层都是使用的PropertySourcePlaceConfigure
这个类实现的
12.纯注解版AOP
12.1编码
1. 原始对象
@Service(@Component)
public class UserServiceImpl implements UserService{
}
2. 创建切面类 (额外功能 切入点 组装切面)
@Aspect
@Component
public class MyAspect {
@Around("execution(* login(..))")
public Object arround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("----aspect log ------");
Object ret = joinPoint.proceed();
return ret;
}
}
3. Spring的配置文件中 声明开启注解AOP
<aop:aspectj-autoproxy />
在配置类上标注 @EnableAspectjAutoProxy注解
12.2切换代理设置
1. 代理创建方式的切换 JDK Cglib
<aop:aspectj-autoproxy proxy-target-class=true|false />
@EnableAspectjAutoProxy(proxyTargetClass=)
2. SpringBoot AOP的开发方式
@EnableAspectjAutoProxy 已经设置好了
1. 原始对象
@Service(@Component)
public class UserServiceImpl implements UserService{
}
2. 创建切面类 (额外功能 切入点 组装切面)
@Aspect
@Component
public class MyAspect {
@Around("execution(* login(..))")
public Object arround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("----aspect log ------");
Object ret = joinPoint.proceed();
return ret;
}
}
Spring AOP 代理默认实现 JDK SpringBOOT AOP 代理默认实现 Cglib
13.纯注解版Spring整合Mybatis
13.1整合回顾
1、数据源(连接池)
使用DataSource
2、SqlSessionFactoryBean
用于创建S(为其注入必要的属性数据源 mapper文件扫描 实体别名)
3、MapperScannerConfigure(创建Dao的代理实现类)
用于创建Dao的代理类对象,配置扫描dao接口并为其注入SqlSessionFactoryBean
13.2编码
@Configuration
//将数据库的配置抽取在外部,使用@PropertySource引入进来
@PropertySource("classpath:db.properties")
//Spring提供的注解,代替了MapperScannerConfigurer,会自动扫描SqlSessionFactoryBean并注入,只需要配置dao接口即可
@MapperScan(basePackages = "com.shwsh.dao")
public class MybatisConfig {
//注入数据库配置文件中的配置
@Value("${user}")
private String username;
@Value("${password")
private String password;
@Value("${url}")
private String url;
@Value("${driver}")
private String driver;
//配置数据源
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUsername(username);
dataSource.setDriverClassName(driver);
dataSource.setPassword(password);
dataSource.setUrl(url);
return dataSource;
}
//配置SqlSessionFactoryBean
@Bean
public SqlSessionFacto
SqlSessionFactoryBean salSessionFactoryBean() {
SqlSessionFactoryBean salSessionFactoryBean = new SqlSessionFactoryBean();
//注入数据源
salSessionFactoryBean.setDataSource(dataSource());
//设置实体类所在包
salSessionFactoryBean.setTypeAliasesPackage("com.shwsh.entity");
//扫描mapper.xml文件位置
// factoryBean.setMapperLocations(new ClassPathResource(""));
//扫描mapper文件的通配写法
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("classpath:mapper/*Mapper.xml");
sqlSessionFactoryBean.setMapperLocations(resources)
return salSessionFactoryBean;
}
这个MapperScannerConfigurer配置被Spring的提供的@MapperScan注解代替
/* @Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setSqlSessionFactoryBeanName("salSessionFactoryBean");
mapperScannerConfigurer.setBasePackage("com.shwsh.entity");
return mapperScannerConfigurer;
}*/
}
14.纯注解Spring事务处理
14.1编码回顾
1、原始对象
2、额外功能(DataSourceTransactionManager)
3、切入点并配置事务属性(@Transactional(islation="",...))
4、整合切面使用标签<tx:annotation-driven trasaction-manager="">
14.2基于注解
//2、额外功能
@Configuration
//4、整合切面使用@EnableTransactionManagement注解,自动扫描DataSourceTransactionManager和切入点@Transactional注解,进行组装
@EnableTransactionManagement
public class TransactionalConfig {
//注入其他配置文件的DataSource,这里没有使用@Import导入其他的配置类,在创建工厂时直接扫描所有的配置类即可
@Autowired
DataSource dataSource;
//配置DataSourceTransactionManager
@Bean
public DataSourceTransactionManager dataSourceTransactionManager(){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
return transactionManager;
}
}