目录
3.3.1使用@Autowired注解开启自动装配模式(按类型)
3.3.2使用@Qualifier注解开启指定名称装配bean(依赖@Autowired)
3.3.4使用@PropertySource注解加载properties文件
一、注解开发定义bean
①使用@Component定义bean
@Component("Service3") public class ServiceImpl3 implements Service3 { @Override public void show() { System.out.println("service3..."); } } @Component public class ServiceImpl4 implements Service4 { @Override public void show() { System.out.println("service4..."); } }
②核心配置文件中通过组件扫描加载bean
<context:component-scan base-package="Service.impl"/>
注意:如果@Component后面没有定义bean的id需要用类型来获取。
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Service3 service3 = (Service3) context.getBean("Service3"); service3.show(); Service4 service4 = context.getBean(Service4.class); service4.show();
二、衍生注解
Spring提供@component注解的三个衍生注解:
@Controller :用于表现层bean定义
@Service : 用于业务层bean定义@Repository :用于数据层bean定义
作用:只是为了区别不同层用的
三、纯注解开发
3.1配置文件基础
Spring3.0升级了纯注解开发模式,使用]ava类替代配置文件,开启了Spring快速开发赛道。
那么如何用Java类代替Spring核心配置文件?
@Configuration //这个注解相当于原来配置文件中<?xml ?> <beans> </beans>这两个标签什么都不加。 @ComponentScan({"Service.impl","Dao.impl"}) //这个注解相当于<beans> </beans>中的<context:component-scan/> public class SpringConfig { }
如何运行?
读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象。
//加载配置文件初始化容器 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //加载配置类初始化容器 ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
新的实现类AnnotationConfigApplicationContext。
public class AppForAnnotation { public static void main(String[] args) { ApplicationContext context =new AnnotationConfigApplicationContext(SpringConfig.class); Service3 service3 = (Service3) context.getBean("Service3"); service3.show(); Service4 service4 = context.getBean(Service4.class); service4.show(); Dao4 dao4 = context.getBean(Dao4.class); dao4.show(); } }
注意:
@Configuration注解用于设定当前类为配置类.。
@ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式。
3.2Bean管理
3.2.1单例控制演示
①编代码
@Repository public class DaoImpl4 implements Dao4 { @Override public void show() { System.out.println("dao.."); } }
public class App10 { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); Dao4 dao1 =context.getBean(Dao4.class); Dao4 dao2 =context.getBean(Dao4.class); System.out.println(dao1); System.out.println(dao2); } }
②输出结果,可见是单例
③在DaoImpl4中新增注释@Scope("prototype")
@Repository @Scope("prototype") public class DaoImpl4 implements Dao4 { @Override public void show() { System.out.println("dao.."); } }
④再次运行输出结果,不一样有木有!
3.2.2生命周期控制演示
①导入maven依赖坐标
<dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> </dependency>
②添加注解
@Repository @Scope("singleton") public class DaoImpl4 implements Dao4 { public void show() { System.out.println("dao.."); } @PostConstruct //构造方法之后 public void init() { System.out.println("init.."); } @PreDestroy //销毁之前 public void destroy() { System.out.println("destroy.."); } }
③先不改上面的运行代码,运行发现没有执行销毁前方法
④如何修改?
public class App10 { public static void main(String[] args) { //ApplicationContext没有close方法,改为AnnotationConfigApplicationContext AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); Dao4 dao1 =context.getBean(Dao4.class); Dao4 dao2 =context.getBean(Dao4.class); System.out.println(dao1); System.out.println(dao2); context.close(); } }
⑤再运行,成功执行destroy方法
3.2.3Bean管理总结
使用@Scope定义bean作用范围
@Scope("singleton")//单例 @Scope("prototype")//非单例
使用@Postconstruct、 @PreDestroy定义bean生命周期
@Postconstruct //构造之后执行 @PreDestroy //销毁前执行
3.3依赖注入
3.3.1使用@Autowired注解开启自动装配模式(按类型)
@Service public class ServiceImpl4 implements Service4 { @Autowired private Dao4 dao4; //@Autowired public void setDao4(Dao4 dao4) { this.dao4 = dao4; } @Override public void show() { System.out.println("service4..."); dao4.show(); } }
@Autowired放在哪里都没有问题,
@Service public class ServiceImpl4 implements Service4 { @Autowired private Dao4 dao4; @Override public void show() { System.out.println("service4..."); dao4.show(); } }
注意︰自动装配基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据,因此无需提供setter方法注意∶自动装配建议使用无参构造方法创建对象(默认),如果不提供对应构造方法﹐请提供唯一的构造方法。
3.3.2使用@Qualifier注解开启指定名称装配bean(依赖@Autowired)
@Repository("dao4") //指定id @Scope("singleton") public class DaoImpl4 implements Dao4 { public void show() { System.out.println("dao4.."); } @PostConstruct //构造方法之后 public void init() { System.out.println("init.."); } @PreDestroy //销毁之前 public void destroy() { System.out.println("destroy.."); } }
@Repository("dao41") //指定id public class DaoImpl5 implements Dao4 { @Override public void show() { System.out.println("dao41.."); } }
@Service public class ServiceImpl4 implements Service4 { @Autowired @Qualifier("dao41") //指定注入id为dao41的bean private Dao4 dao4; @Override public void show() { System.out.println("service4..."); dao4.show(); } }
public class App11 { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); Service4 service4 =context.getBean(Service4.class); service4.show(); } }
运行结果:
从结果可以看出,指定注入的是dao41,但是dao4的init方法也被执行。
注意:@Qualifier注解无法单独使用,必须配合@Autowired注解使用
3.3.3使用@Value实现简单类型注入
@Repository("dao41") public class DaoImpl5 implements Dao4 { @Value("ylm") private String name; @Override public void show() { System.out.println("dao41.."+name); } }
运行结果:
3.3.4使用@PropertySource注解加载properties文件
@Repository("dao41") public class DaoImpl5 implements Dao4 { @Value("ylm") private String name; @Value("${jdbc.password}") private String password; @Override public void show() { System.out.println("dao41.." + name + password); } }
@Configuration @ComponentScan({"Service.impl","Dao.impl"}) @PropertySource("jdbc.properties") //加载配置文件,多个配置文件依旧使用数组,但是不支持使用通配符 //@PropertySource({"jdbc.properties","jdbc2.properties"}) //@PropertySource({"classpath:jdbc.properties","classpath:jdbc2.properties"}) //通配符是会报错的*.properties , classpath*:这两种都会报错。 public class SpringConfig { }
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/brand jdbc.user=root jdbc.password=123456
运行结果:
注意∶路径仅支持单一文件配置,多文件请使用数组格式配置,不允许使用通配符*
3.4第三方bean管理
3.4.1使用@Bean配置第三方bean
配置类
@Configuration public class SpringConfig { //1.定义一个方法获得要管理的对象 //2.添加@Bean,表示当前方法返回的是一个bean @Bean public DataSource dataSource(){ DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setDriverClassName("com.mysql.jdbc.Driver"); druidDataSource.setUrl("jdbc:mysql://localhost:3306/brand"); druidDataSource.setUsername("root"); druidDataSource.setPassword("123456"); return druidDataSource; } }
运行代码
public class App12 { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); DataSource dataSource = context.getBean(DataSource.class); System.out.println(dataSource); } }
运行结果
这样写有个问题,就是如果都这样写SpringConfig主配置类得写多少?接着看下面。
3.4.2使用独立的配置类管理第三方bean
方式一:扫描式
这样改进,拆成专用配置类,放在包Config下,在主配置类SpringConfig里使用@ComponentScan注解扫描配置类所在的包,加载对应的配置类信息,都添加@Configuration。
SpringConfig
@Configuration @ComponentScan({"Config"}) public class SpringConfig { }
ThirdPartySpringConfig
@Configuration public class ThirdPartySpringConfig { //1.定义一个方法获得要管理的对象 //2.添加@Bean,表示当前方法返回的是一个bean @Bean public DataSource dataSource(){ DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setDriverClassName("com.mysql.jdbc.Driver"); druidDataSource.setUrl("jdbc:mysql://localhost:3306/brand"); druidDataSource.setUsername("root"); druidDataSource.setPassword("123456"); return druidDataSource; } }
再次运行App12:
(其实我在测试ComponentScan时,不加ComponentScan,也不写@Configuration,依然能用,只要有个@Bean就可以,不知道为何,可能是为了更好的理解这样的思维方式)。
这样还是不推荐,推荐使用的导入式,就是下面的方法。
方式二:导入式
推荐使用@Import,手动加入配置类到核心配置,此注解只能添加一次,多个数据请用数组格式
SpringConfig
@Configuration @Import({ThirdPartySpringConfig.class}) public class SpringConfig { }
ThirdPartySpringConfig
//不用再写@Configuration public class ThirdPartySpringConfig { //1.定义一个方法获得要管理的对象 //2.添加@Bean,表示当前方法返回的是一个bean @Bean public DataSource dataSource(){ DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setDriverClassName("com.mysql.jdbc.Driver"); druidDataSource.setUrl("jdbc:mysql://localhost:3306/brand"); druidDataSource.setUsername("root"); druidDataSource.setPassword("123456"); return druidDataSource; } }
运行结果:
3.4.3实现为第三方bean注入资源
依赖注入类型:
①简单类型注入(使用@Value),用成员变量。
②引用类型注入, 用方法形参。引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象。
ThirdPartySpringConfig
public class ThirdPartySpringConfig { //1.定义一个方法获得要管理的对象 //2.添加@Bean,表示当前方法返回的是一个bean //简单类型 @Value("com.mysql.jdbc.Driver") private String driver; @Value("jdbc:mysql://localhost:3306/brand") private String url; @Value("root") private String userName; @Value("123456") private String password; @Bean public DataSource dataSource(NewDao newDao){ //引用类型,NewDao按照类型自动装配 System.out.println(newDao); DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setDriverClassName(driver); druidDataSource.setUrl(url); druidDataSource.setUsername(userName); druidDataSource.setPassword(password); return druidDataSource; } }
NewDao
@Repository public class NewDaoImpl implements NewDao { @Override public void show() { System.out.println("NewDao"); } }
运行代码
public class App13 { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); DataSource dataSource = context.getBean(DataSource.class); System.out.println(dataSource); } }
运行结果:
总结
XML配置与注解配置比较:
功能 XML配置 注解 定义bean bean标签
·id属性
·class属性
@Component
·@Controller
·@service
·@Repository
@ComponentScan
设置依赖注入 setter注入( set方法)
·引用类型/简单类型构造器注入(构造方法)
·引用类型/简单类型自动装配
@Autowired
·@Qualifier
@Value
配置第三方bean bean标签
静态工厂、实例工厂、FactoryBean
@Bean 作用范围 scope属性 @Scope 生命周期 标准接口
·init-method
·destroy-method@PostConstructor
@PreDestroy
标红表示常用,可以重点学习复习。