Spring IoC — 基于注解的配置
基于XML的配置,Bean定义信息和Bean实现类本身是分离的,而采用基于注解的配置方式时,Bean定义信息即通过在Bean实现类上标注注解实现。
@Component:对类进行标注,Spring容器自动将POJO转换为容器管理的Bean;
@Repository:用于对DAO实现类进行标注;
@Service:用于对Service实现类进行标注;
@Controller:用于对Controller实现类进行标注。
1、自动装配Bean:
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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd" > <context:component-scan base-package="com.ioc.ch4_10"/> <bean id="ls" class="com.ioc.ch4_10.LogonService"></bean> <!-- context:component-scan base-package="com.baobaotao" resource-pattern="anno/*.class"/ --> <!-- context:component-scan base-package="com.baobaotao"> <context:include-filter type="regex" expression="com\.baobaotao\.anno.*Dao"/> <context:include-filter type="regex" expression="com\.baobaotao\.anno.*Service"/> <context:exclude-filter type="aspectj" expression="com.baobaotao..*Controller+"/> </context:component-scan --> </beans>
LogDao类:
package com.ioc.ch4_10; import org.springframework.stereotype.Component; @Component("logDao") public class LogDao { }
UserDao_1类:
package com.ioc.ch4_10; import org.springframework.stereotype.Component; @Component("userDao_1") //自动被Spring容器识别,Spring容器自动将POJO转换为容器管理的Bean //等价于XML配置的<bean id="userDao_1" class="com.ioc.ch4_10.UserDao_1"> public class UserDao_1 { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "UserDao_1{" + "name='" + name + '\t' + '}'; } public UserDao_1() { System.out.println("userDao"); } }
UserDao_2类:
package com.ioc.ch4_10; import org.springframework.stereotype.Component; /** * Created by gao on 16-3-25. */ @Component("userDao_2") public class UserDao_2 { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "UserDao_2{" + "name='" + name + '\t' + '}'; } public UserDao_2() { System.out.println("userDao_2"); } }
UserDao_3类:
package com.ioc.ch4_10; import org.springframework.stereotype.Component; /** * Created by gao on 16-3-25. */ @Component("userDao_3") public class UserDao_3 { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "UserDao_3{" + "name='" + name + '\t' + '}'; } public UserDao_3() { System.out.println("userDao_3"); } }
LogonService类:
package com.ioc.ch4_10; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; @Service public class LogonService{ //使用@Autowired进行自动注入 @Autowired private LogDao logDao; @Autowired private UserDao_1 userDao1; //使用@Autowired的required属性,设置为false表示找不到匹配的Bean完成注入也不要抛出异常 @Autowired(required = false) private UserDao_2 userDao_2; //使用@Qualifier指定注入Bean的名称 @Autowired @Qualifier("userDao_3") private UserDao_3 userDao_3; public LogDao getLogDao() { return logDao; } public UserDao_1 getUserDao1() { return userDao1; } public UserDao_2 getUserDao2() { return userDao_2; } public UserDao_3 getUserDao3() { return userDao_3; } public void printSomething(){ userDao1.setName("LogonService-userDao1"); System.out.println(userDao1.toString()); userDao_2.setName("LogonService-userDao2"); System.out.println(userDao_2.toString()); userDao_3.setName("LogonService-userDao3"); System.out.println(userDao_3.toString()); } }
LoginService_2类:
package com.ioc.ch4_10; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; /** * Created by gao on 16-3-25. */ @Service public class LogonService_2 { private LogDao logDao; private UserDao_1 userDao_1; //自动将LogDao传给方法入参 @Autowired public void setLogDao(LogDao logDao) { System.out.println("auto setlogdao"); this.logDao = logDao; } //自动将名为userDao的Bean传给方法入参 @Autowired public void setUserDao_1(UserDao_1 userDao_1) { System.out.println("auto setuserdao"); this.userDao_1 = userDao_1; } @Autowired public void init(@Qualifier("userDao_1")UserDao_1 userDao,LogDao logDao){ System.out.println("multi param inject"); this.userDao_1 = userDao; this.logDao =logDao; } }
测试类:
package com.ioc.ch4_10; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Created by gao on 16-3-25. */ public class Test { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com\\ioc\\ch4_10\\beans.xml"); LogonService ls = (LogonService) ctx.getBean("ls"); ls.printSomething(); } }
输出结果:
userDao
userDao_2
userDao_3
multi param inject
auto setlogdao
auto setuserdao
UserDao_1{name='LogonService??userDao1}
UserDao_2{name='LogonService-userDao2 }
UserDao_3{name='LogonService-userDao3 }
2、对集合类进行标注
Plugin接口:
package com.ioc.ch4_10; public interface Plugin { }
onePlugin类:
package com.ioc.ch4_10; import org.springframework.stereotype.Component; @Component public class OnePlugin implements Plugin { }
twoPlugin类:
package com.ioc.ch4_10; import org.springframework.stereotype.Component; @Component public class TwoPlugin implements Plugin { }
MyComponent类:
package com.ioc.ch4_10; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; @Component public class MyComponent { //Spring会将容器中所有类型为Plugin的Bean注入到这个变量中 @Autowired(required=false) private List<Plugin> plugins; public List<Plugin> getPlugins() { return plugins; } }
mycomponent.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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="com.ioc.ch4_10"> <context:include-filter type="aspectj" expression="com.baobaotao.anno.*Plugin+"/> <context:include-filter type="aspectj" expression="com.baobaotao.anno.MyComponent"/> </context:component-scan> </beans>
MyComponentTest类:
package com.ioc.ch4_10; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyComponentTest { public static void main(String[] args) throws Throwable { ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com\\ioc\\ch4_10\\mycomponent.xml"); MyComponent myComponent = ctx.getBean(MyComponent.class); System.out.println("pulgin.size:"+myComponent.getPlugins().size()); } }
输出结果:
userDao
userDao_2
userDao_3
multi param inject
auto setlogdao
auto setuserdao
pulgin.size:2
3、Bean作用范围及生命过程方法
使用Scope指定作用范围
package com.ioc.ch4_10; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; //指定Bean的作用范围为prototype @Scope(BeanDefinition.SCOPE_PROTOTYPE) @Component public class Car { private int maxSpeed; public String brand; private double price; ...... }
Boss类:
package com.ioc.ch4_10; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.annotation.Resource; @Component public class Boss { private Car car; public Boss(){ System.out.println("construct..."); } @Resource private void setCar(Car car){ System.out.println("execute in setCar"); this.car = car; } @PostConstruct private void init1(){ System.out.println("execute in init1"); } @PostConstruct private void init2(){ System.out.println("execute in init1"); } @PreDestroy private void destory1(){ System.out.println("execute in destory1"); } @PreDestroy private void destory2(){ System.out.println("execute in destory2"); } }
测试类:
package com.ioc.ch4_10; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Created by gao on 16-3-25. */ public class Test { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com\\ioc\\ch4_10\\beans.xml"); Car car1 = (Car) ctx.getBean("car"); Car car2 = (Car) ctx.getBean("car"); System.out.println(car1 == car2); //false UserDao_2 ud1 = (UserDao_2) ctx.getBean("userDao_2"); UserDao_2 ud2 = (UserDao_2) ctx.getBean("userDao_2"); System.out.println(ud1 == ud2); //true ((ClassPathXmlApplicationContext)ctx).destroy(); } }
输出结果:
construct...
execute in setCar
execute in init1
execute in init1
false
true
execute in destory2
execute in destory1