springboot实战电商我的项目mall4j (https://gitee.com/gz-yami/mall4j)
java商城零碎源码
1. bean注册
咱们有个Person类
public class Person { private Integer age; private String name; public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person [age=" + age + ", name=" + name + "]"; }}
1.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="person" class="com.opgame.spring.Person"> <property name="age" value="18"/> <property name="name" value="张三"/> </bean></beans>
应用person对象进行测试
@Testpublic void testBean() { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Person person = (Person)context.getBean("person"); System.out.println(person);}
1.2 应用annotation代替xml注册
创立一个带有@Configuration
的java类,应用 @Bean
进行注册
@Configuration // 通知spring这个是一个config类public class BeansConfig { // 给容器注册一个bean,类型为返回值类型,默认id为办法名,在bean注解中设置id @Bean("person") public Person person() { Person person = new Person(); person.setAge(20); person.setName("李四"); return person; }}
应用person对象进行测试
@Testpublic void testBean() { ApplicationContext context = new AnnotationConfigApplicationContext(BeansConfig.class); Person person = (Person)context.getBean("person"); System.out.println(person);}
2 exclude、include filter
在传统的spring mvc我的项目中为了使事务起效,咱们通常在context.xml
进行exclude @Controller
类,在mvc.xml
进行include @Controller
,当咱们应用一些第三方类库的时候,有时也须要对某些类进行排除扫码,那该怎么办呢?
2.1 传统xml排除与导入扫描类
context.xml(须要context命名空间)
<context:component-scan base-package="com.opgame"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/></context:component-scan>
mvx.xml
<!-- use-default-filters默认ture,默认扫描@Component @Repository @Service @Controller --> <context:component-scan base-package="com.opgame" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
2.2应用注解的模式排除与导入扫描类
@ComponentScan 注解应用
- value:指定要扫描的包
- excludeFilters = Filter[] :指定扫描的时候依照什么规定排除那些组件
- includeFilters = Filter[] :指定扫描的时候只须要蕴含哪些组件
- useDefaultFilters:是否应用默认的Filters
Filter
- FilterType.ANNOTATION:依照注解
- FilterType.ASSIGNABLE_TYPE:依照给定的类型
- FilterType.ASPECTJ:应用ASPECTJ表达式
- FilterType.REGEX:应用正则指定
- FilterType.CUSTOM:应用自定义规定
- classes:ANNOTATION、ASSIGNABLE_TYPE、CUSTOM 给定的类
- pattern:ASPECTJ、REGEX 给定的表达式
@Configuration // 通知spring这个是一个config类@ComponentScan(value="com.opgame",useDefaultFilters=false,includeFilters= { @Filter(type=FilterType.ANNOTATION,classes= {Controller.class})},excludeFilters= { @Filter(type=FilterType.ASSIGNABLE_TYPE,classes= {PersonController.class})})public class BeansConfig{ }
自定义规定
// 实现org.springframework.core.type.filter.TypeFilter 接口public class BeanTypeFilter implements TypeFilter{ /** * @param metadataReader 获取被spring扫描到的以后类的元数据 * @param metadataReaderFactory 获取元数据的工厂,用于获取其余类的信息 */ public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { // 获取以后类注解元信息 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); // 获取以后类的类信息 ClassMetadata classMetadata = metadataReader.getClassMetadata(); // 获取以后类的资源(类门路) Resource resource = metadataReader.getResource(); // 如果以后类名含有person则配胜利 if(classMetadata.getClassName().contains("person")) { return true; } return false; }}
3. 作用域与懒加载
3.1 xml
<!-- 默认scope="singleton" 单例--><!-- lazy-init="true" 当须要用到的时候才创建对象,默认为spring初始化时创立--><bean id="person" class="com.opgame.spring.Person" scope="singleton" lazy-init="true"> <property name="age" value="18"/> <property name="name" value="张三"/></bean>
3.2 注解
@Lazy@Scope("singleton")@Bean("person")public Person person() { Person person = new Person(); person.setAge(20); person.setName("李四"); return person;}
4 按条件注册
在有的时候,咱们编写框架,又或者编写代码,在不同环境时须要切换到不同的实现办法。那么在何时加载那品种的实现,spring为咱们提供了这个注解
在spring中应用@Conditional
注解实现按需加载类。
@Conditional({ LinuxCondition.class})public Person person1() { Person person = new Person(); person.setAge(18); person.setName("李小四"); return person;}
// 实现 org.springframework.context.annotation.Condition 接口public class LinuxCondition implements Condition{ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // 获取ioc应用的beanfactory ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); // 获取类加载器 ClassLoader classLoader = context.getClassLoader(); // 获取以后环境 Environment environment = context.getEnvironment(); // 获取bean注册类 BeanDefinitionRegistry registry = context.getRegistry(); // 判断是否蕴含person对象 boolean hasPerson = registry.containsBeanDefinition("person"); if (!hasPerson) { return false; } // 判断是否属于linux 环境 if(environment.getProperty("os.name").contains("linux")) { return true; } return false; }}
在启动程序时设置 vm arguments 也能够查看Environment相干的笔记
-Dos.name=linux
也能够在
在spring boot中,应用@ConditionalOnMissingBean(name="xxx")
@ConditionalOnMissingBean(xxx.class)
也能够判断当没有某些类或者办法的时候进行注册。
5. 应用import进行注册
现有多个类
class Blue {}class Color {}class Red {}
5.1 进行简略的注册
当咱们须要无参注册的时候,能够应用@import
进行注册如:
@Configuration@Import({Blue.class,Red.class})public class BeansConfig { }
其中bean id为类全名称 如com.opgame.spring.bean.Blue
com.opgame.spring.bean.Red
相当于
@Configurationpublic class BeansConfig { @Bean("com.opgame.spring.bean.Blue") public Blue blue() { return new Blue(); } @Bean("com.opgame.spring.bean.Red") public Red red() { return new Red(); }}
5.2 应用ImportSelector 进行类名注册
// 自定义逻辑返回须要导入的组件// 实现org.springframework.context.annotation.ImportSelector 接口public class BeanImportSelector implements ImportSelector{ /** * importingClassMetadata: 能够获取以后被标注@Import注解的所有注解元信息 * 即以后例子中 BeansConfig.class的所有注解的元信息 */ public String[] selectImports(AnnotationMetadata importingClassMetadata) { // 不容许返回null return new String[] {"com.opgame.spring.bean.Blue","com.opgame.spring.bean.Red"}; }}
@Configuration@Import({BeanImportSelector.class})public class BeansConfig { }
5.3 ImportBeanDefinitionRegistrar 注册一个bean到容器中
此时注册的是BeanDefinition,也就是bean的定义信息,而spring 会依据bean的定义信息,进行bean的注册!也就是此时并没有注册bean!!!
// 实现org.springframework.context.annotation.ImportBeanDefinitionRegistrar接口public class BeansImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{ /** * importingClassMetadata:以后config类的注解信息(beansConfig) * registry:Bean注册类,能够在此把所有须要增加到容器中的bean调用 BeanDefinitionRegistry.registerBeanDefinition()办法进行注册 */ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean hasBlue = registry.containsBeanDefinition("com.opgame.spring.bean.Blue"); boolean hasRed = registry.containsBeanDefinition("com.opgame.spring.bean.Red"); // 如果有红色和蓝色,则注册一个id为color的 Color对象 if (hasBlue && hasRed) { RootBeanDefinition beanDefinition = new RootBeanDefinition(Color.class); registry.registerBeanDefinition("color", beanDefinition); } }}
@Configuration@Import({Blue.class,Red.class,BeansImportBeanDefinitionRegistrar.class})public class BeansConfig { }
6 实现FactoryBean<?>接口注册bean
// 实现org.springframework.beans.factory.FactoryBean接口public class PersonFactoryBean implements FactoryBean<Person>{ // 结构person对象 public Person getObject() throws Exception { return new Person(); } // 获取以后对象的类型 public Class<?> getObjectType() { return Person.class; } // 是否为单例 public boolean isSingleton() { return true; }}
@Configurationpublic class BeansConfig { @Bean public PersonFactoryBean personFactoryBean() { return new PersonFactoryBean(); }}
应用person对象进行测试
@Testpublic void testBean() { ApplicationContext context = new AnnotationConfigApplicationContext(BeansConfig.class); context.getBean("personFactoryBean").getClass(); // com.opgame.spring.Person // 获取该工厂结构除的bean对象须要&符号 Person person = (Person)context.getBean("&personFactoryBean"); // 不应用&则获取工厂自身 PersonFactoryBean personFactoryBean = (PersonFactoryBean)context.getBean("personFactoryBean"); System.out.println(person);}
7 通过BeanDefinitionBuilder创立
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(User.class);builder.addPropertyValue("id", 1);builder.addPropertyValue("name", "李四");registry.registerBeanDefinition("user", builder.getBeanDefinition());
springboot实战电商我的项目mall4j (https://gitee.com/gz-yami/mall4j)
java商城零碎源码