一.装配Bean的三种方法
1.在xml中显示配置(有些我们无法更改代码的类,可以通过xml方式配置使用)
2.在Java的接口和类中显示配置(第二考虑,避免xml泛滥,也更容易)
3.隐式Bean的发现机制和自动装配原则。(最优先,减少程序开发者的决定权,简单又不失灵活)
当配置的类是你自身开发的工程,应该优先考虑java配置为主,Java配置又分自动装配和Bean名称配置,在没有歧义的基础上,优先使用自动装配,这样就能减少大量的xml配置,如果所需配置的类不是你自己开发的,建议使用xml方式。
二.装配详细方法
1.装配简易值
<bean id="source" class="com.hly.spring.pojo.springIOC.Source"> <property name="fruit" value="橙汁"/><!--property:构造方法的参数--> <property name="sugar" value="无糖"/> <property name="size" value="3"/> </bean>
<bean id="juiceMaker" class="com.hly.spring.pojo.springIOC.JuiceMaker" init-method="init" destroy-method="destroy"> <property name="beverageShop" value="避风塘"/> <property name="source" ref="source"/><!--ref:引用之前定义的bean--> </bean>
1.1.id属性,spring能找到这个bean的编号
1.2.class属性,一个类的全限定名
1.3.property属性,定义类的属性,name是属性的名称,value是其值。
1.4.ref属性为应用对应的bean。
2.装配集合
public class ComplexAssemble { private Long id; private List<String> list; private Map<String,String> map; //主要用于读取Java的配置文件,各种语言都有自己所支持的配置文件,配置文件中很多变量是经常改变的,这样做也是为了方便用户,让用户能够脱离程序本身去修改相关的变量设置 private Properties props; private Set<String> set; private String[]arrays; private List<User> listUser;
<!--装配集合--> <bean id="complexAssemble" class="com.hly.spring.pojo.springBean.ComplexAssemble"> <property name="id" value="1"/> <property name="list"> <list> <!--多个value元素设置值--> <value>value-1ist-1</value> <value>value-1ist-2</value> </list> </property> <property name="map"> <map> <!--entry元素设置值,包含一个键和一个值得设置--> <entry key="key1" value="value-key-1"/> <entry key="key2" value="value-key-2"/> <!--应用bean用的是key-ref,value-ref--> </map> </property> <property name="props"> <props> <prop key="prop1">values-1</prop> <prop key="prop2">values-2</prop> </props> </property> <property name="set"> <set> <value>values1</value> <value>values2</value> </set> </property> <property name="arrays"> <array> <value>value-array-1</value> <value>value-array-2</value> </array> </property> <property name="listUser"> <list> <!--引用之前定义的bean--> <ref bean="user2"/> </list> </property> </bean>
3.命名空间装配
暂略
4.通过注解装配Bean
4.1装配原则
1.更多的时候考虑注解装配Bean(annotation),减少xml的配置,注解功能更加强大,既能试下xml的功能,也提供了自动装配的功能,更加有利于程序开发。
2.两种方式让SpringIOC容器发现Bean
2.1组件扫描,通过定义资源方式,SpringIOC容器扫描对应的包,从而把Bean装配起来。
2.1自动装配,通过注解定义,使得一些依赖关系可以通过注解来完成。
3.目前最流行以注解为主,xml为辅
4.设么时候用xml
4.1系统存在公共的配置文件,properties,xml文件等,写在注解里,公共资源就分散了
4.2有时一些类来自第三方,xml来完成就会更加明确一些。
4.2.使用@Component装配Bean
ps
@Service用于标注业务层组件
@Controller用于标注控制层组件(如struts中的action)
@Repository用于标注数据访问组件,即DAO组件
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注
虽然有了@Autowired,但是我们还是要写一堆bean的配置文件,相当麻烦,而@Component就是告诉spring,我是pojo类,把我注册到容器中吧,spring会自动提取相关信息。
** * @author :hly * @date :2018/5/10 */ @Component(value = "role") public class Role { @Value("1") private int rolerId; @Value("hly") private String roleName; @Value("god") private String roleNote;
1.@Component代表SpringIOC把这个类扫描成Bean的实例,Value可以简写成@Component("1");,不写的话,@SpringIOC就默认为类名,首写字母为小写为id。
2.id是int类型,注入时候,Spring会自动转化类型。
@ComponentScan public class PojoConfig { }
上面这个类是告诉SpringIOC去哪里扫描它,包名要和上面的Role包名保持一致,这个类什么都没有。@ComponentScan默认是扫描当前包的路径的Java类。
接下来就可以测试了。
import com.hly.spring.pojo.springBean.PojoConfig; import com.hly.spring.pojo.springBean.Role; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * @author :hly * @date :2018/5/10 */ public class BeanTest { public static void main(String []y){ ApplicationContext context = new AnnotationConfigApplicationContext(PojoConfig.class); Role role = context.getBean(Role.class); System.err.print(role.getRolerId()); } }
3.上面扫描的弊端在于只能扫描当前的包,接下来介绍怎么扫描别的包和多个包。
//@ComponentScan(basePackageClasses = {Role.class, RoleServiceImpl.class}) @ComponentScan(basePackages = {"com.hly,spring.pojo.springBean","com.hly,spring,service"}) public class ApplicationConfig { }basePackages的可读性会更好一些,在项目中优先选择他,但在需要大量重构的项目中不要选择,选择另一个IDE会提示包被改动的报错,如果在项目中重复定义多个包,会造成对一个Bean进行多次扫描,重复创建对
@ComponentScan(basePackageClasses = {Role.class, RoleServiceImpl.class},basePackages = {"com.hly,spring.pojo.springBean","com.hly,spring,service"})
上面这个类代替PojoConfig这个类,另外再定义两个类
package com.hly.spring.service; import com.hly.spring.pojo.springBean.Role; /** * @author :hly * @date :2018/5/10 */ public interface RoleService { public void printRoleInfo(Role role); }
package com.hly.spring.ServiceImpl; import com.hly.spring.pojo.springBean.Role; import com.hly.spring.service.RoleService; import org.springframework.stereotype.Component; /** * @author :hly * @date :2018/5/10 */ //@Component表明他是Spring所需要的Bean @Component public class RoleServiceImpl implements RoleService { @Override public void printRoleInfo(Role role) { System.out.print(role.getRoleName()); } }
测试类
public class BeanTest { public static void main(String []y){ // ApplicationContext context = new AnnotationConfigApplicationContext(PojoConfig.class); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class); Role role = context.getBean(Role.class); RoleService roleService = context.getBean(RoleService.class); roleService.printRoleInfo(role); } }
4.3自动注入@Autowired
(@Component是装配,@Autowired是注入装配的@Component)
1.@Autowired表示被修饰的类需要注入对象,spring会扫描所有被@Autowired标注的类,然后根据 类型 在ioc容器中找到匹配的类注入。@Autowired自动装配(按类注入),通常情况,Spring是先完成Bean的定义和生成,然后寻找要注入的资源,如果发现@Autowire的这个注解,就会在Bean中进行查找,然后找到对应的类型,将其注入进来。
代码中使用@Autowired或@Resource注解方式进行装配,这两个注解的区别是:@Autowired 默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。
package com.hly.spring.service; import com.hly.spring.pojo.springBean.Role; /** * @author :hly * @date :2018/5/10 */ public interface RoleService { public void printRoleInfo(); }
package com.hly.spring.ServiceImpl; import com.hly.spring.pojo.springBean.Role; import com.hly.spring.service.RoleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * @author :hly * @date :2018/5/10 */ public class RoleServiceImpl implements RoleService { //SpringIOC定位所有的Bean后,这个字段需要按类型注入,IOC就会寻找资源,然后将其注入。 //requiredIOC找不到对应的资源,没有异常抛出 @Autowired(required = false) private Role role = null; //@Autowired自动注入 @Override public void printRoleInfo() { System.out.print(role.getRoleName()); } //@Autowired也可以方法配置 @Autowired public void setRole(Role role){ this.role=role; } }
按类注入role后,printRoleInfo没有参数。
2.@Primary优先注入,RoleService有两个实现类,IOC容器无法判断把哪个对象注入进来
public interface RoleService { //public void printRoleInfo(); }
@Component public class RoleServiceImpl implements RoleService { @Override public void printRoleInfo(Role role) { System.out.print(role.getRoleName()); } }
/** * @author :hly * @date :2018/5/10 */ @Component("roleService3") @Primary public class RoleServiceImpl2 implements RoleService { @Override public void printRoleInfo(Role role) { System.out.print(role.getRoleNote()); } }
public class BeanTest { public static void main(String []y){ // ApplicationContext context = new AnnotationConfigApplicationContext(PojoConfig.class); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class); Role role = context.getBean(Role.class); RoleService roleService = context.getBean(RoleService.class); roleService.printRoleInfo(role); } }
输出的是RoleServiceImpl2的方法。
3.@Qualifier("")按名称注入
4.4使用@Bean转配Bean
1.@Componet只能注解在类上,不能注解在方法上
import com.hly.spring.pojo.springIOC.JuiceMaker; import com.hly.spring.pojo.springIOC.Source; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author :hly * @date :2018/5/9 */ @Configuration public class Juice { @Bean(name = "juiceMaker2",initMethod = "init",destroyMethod = "myDestroy") public JuiceMaker juiceMaker(){ JuiceMaker juiceMaker2 = new JuiceMaker(); juiceMaker2.setBeverageShop("茶"); Source source = new Source(); source.setFruit("芒果"); source.setSize(1); source.setSugar("无糖"); juiceMaker2.setSource(source); return juiceMaker2; } public static void main(String []hly){ //ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-cfg.xml"); //AnnotationConfigApplicationContext这个容器是为注解方式设计的 ApplicationContext ctx = new AnnotationConfigApplicationContext(Juice.class); JuiceMaker juiceMaker = (JuiceMaker)ctx.getBean("juiceMaker2"); System.out.println(juiceMaker.makeJuice()); //ctx.close(); } }
ps
@Configuration:https://www.cnblogs.com/duanxz/p/7493276.html
@Configuration可理解为用spring的时候xml里面的<beans>标签